Initial commit
This commit is contained in:
commit
1c7148f25b
48 changed files with 19200 additions and 0 deletions
14
Makefile
Normal file
14
Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# The Azure agents needs CMS to obtain the SSH public keys.
|
||||
# LibreSSL has removed CMS, so either use OpenSSL to decrypt CMS
|
||||
# messages or compile the old CMS code for LibreSSL.
|
||||
#
|
||||
.ifdef USE_OPENSSL
|
||||
MAKE_FLAGS+= USE_OPENSSL=1
|
||||
.else
|
||||
SUBDIR= cms
|
||||
.endif
|
||||
|
||||
SUBDIR+= agent
|
||||
|
||||
.include <bsd.subdir.mk>
|
4
README.md
Normal file
4
README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
NOTHING TO SEE HERE
|
||||
===================
|
||||
|
||||
*...yet*
|
20
agent/Makefile
Normal file
20
agent/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
|||
PROG= cloud-agent
|
||||
SRCS= main.c xml.c azure.c cloudinit.c http.c log.c
|
||||
BINDIR= /usr/local/libexec
|
||||
|
||||
.ifdef USE_OPENSSL
|
||||
CFLAGS+= -DUSE_OPENSSL=1
|
||||
.endif
|
||||
|
||||
CFLAGS+= -Wall
|
||||
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
|
||||
CFLAGS+= -Wmissing-declarations
|
||||
CFLAGS+= -Wshadow -Wpointer-arith
|
||||
CFLAGS+= -Wsign-compare -Wcast-qual
|
||||
|
||||
LDADD+= -lexpat -ltls -lssl -lcrypto
|
||||
DPADD+= ${LIBEXPAT} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO}
|
||||
|
||||
NOMAN= yes
|
||||
|
||||
.include <bsd.prog.mk>
|
791
agent/azure.c
Normal file
791
agent/azure.c
Normal file
|
@ -0,0 +1,791 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "http.h"
|
||||
#include "xml.h"
|
||||
|
||||
static struct azure_config {
|
||||
const char *az_apiversion;
|
||||
unsigned int az_incarnation;
|
||||
const char *az_privkey;
|
||||
const char *az_pubkey;
|
||||
const char *az_certs;
|
||||
char *az_pubkeyval;
|
||||
char *az_container;
|
||||
} az_config = {
|
||||
.az_apiversion = "2015-04-05",
|
||||
.az_incarnation = 1,
|
||||
.az_privkey = "/var/db/azure-transport.key",
|
||||
.az_pubkey = "/var/db/azure-transport.pub",
|
||||
.az_certs = "/var/db/azure-certificates.pem"
|
||||
};
|
||||
|
||||
static struct httpget
|
||||
*azure_request(struct system_config *, struct xml *,
|
||||
const char *, const void *, size_t, struct httphead **);
|
||||
|
||||
static int azure_keys(struct system_config *);
|
||||
static int azure_getpubkeys(struct system_config *);
|
||||
static int azure_getendpoint(struct system_config *);
|
||||
static int azure_getovfenv(struct system_config *);
|
||||
static int azure_versions(struct system_config *);
|
||||
static int azure_goalstate(struct system_config *);
|
||||
static int azure_certificates(struct system_config *);
|
||||
static int azure_reporthealth(struct system_config *, const char *);
|
||||
|
||||
int
|
||||
azure(struct system_config *sc)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
/* Apply defaults */
|
||||
if ((sc->sc_username = strdup("azure-user")) == NULL) {
|
||||
log_warnx("failed to set default user");
|
||||
goto done;
|
||||
}
|
||||
sc->sc_cdrom = "/dev/cd0c";
|
||||
sc->sc_ovfenv = "/var/db/azure-ovf-env.xml";
|
||||
sc->sc_priv = &az_config;
|
||||
|
||||
if (azure_getendpoint(sc) != 0) {
|
||||
log_warnx("failed to get endpoint");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (azure_getovfenv(sc) != 0) {
|
||||
log_warnx("failed to get ovf-env.xml");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (azure_versions(sc) != 0) {
|
||||
log_warnx("failed to get endpoint versions");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (azure_goalstate(sc) != 0) {
|
||||
log_warnx("failed to get goalstate");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (azure_keys(sc) != 0) {
|
||||
log_warnx("failed to get transport keys");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (azure_certificates(sc) != 0) {
|
||||
log_warnx("failed to get certificates");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (azure_reporthealth(sc, "Ready") != 0) {
|
||||
log_warnx("failed to report health");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
free(az_config.az_container);
|
||||
free(az_config.az_pubkeyval);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
azure_keys(struct system_config *sc)
|
||||
{
|
||||
struct azure_config *az = sc->sc_priv;
|
||||
int fd, i;
|
||||
const char *k[4];
|
||||
FILE *fp = NULL, *keyfp = NULL;
|
||||
char buf[BUFSIZ];
|
||||
char *keybuf = NULL;
|
||||
size_t keybufsz;
|
||||
|
||||
k[0] = az->az_privkey;
|
||||
k[1] = az->az_pubkey;
|
||||
k[2] = az->az_certs;
|
||||
k[3] = NULL;
|
||||
|
||||
if (access(az->az_privkey, R_OK) != 0 ||
|
||||
access(az->az_pubkey, R_OK) != 0) {
|
||||
/* Ugh, we must generate the files before writing the keys */
|
||||
for (i = 0; k[i] != NULL; i++) {
|
||||
if ((fd = open(k[i],
|
||||
O_WRONLY|O_CREAT|O_TRUNC, 0600)) == -1)
|
||||
return (-1);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
fd = disable_output(sc, STDERR_FILENO);
|
||||
|
||||
/* Now generate the actual transport keys */
|
||||
if (shell("openssl", "req",
|
||||
"-x509", "-nodes", "-subj", "/CN=LinuxTransport",
|
||||
"-days", "32768", "-newkey", "rsa:2048",
|
||||
"-keyout", az->az_privkey,
|
||||
"-out", az->az_pubkey,
|
||||
NULL) != 0) {
|
||||
log_debug("%s: failed to generate keys", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
enable_output(sc, STDERR_FILENO, fd);
|
||||
}
|
||||
|
||||
if ((fp = fopen(az->az_pubkey, "r")) == NULL) {
|
||||
log_debug("%s: failed to read public key", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((keyfp = open_memstream(&keybuf, &keybufsz)) == NULL) {
|
||||
log_debug("%s: failed to open public key stream", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* We have to read the public key into a single base64 line */
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
buf[strcspn(buf, "\r\n")] = '\0';
|
||||
|
||||
if (strcmp("-----BEGIN CERTIFICATE-----", buf) == 0 ||
|
||||
strcmp("-----END CERTIFICATE-----", buf) == 0 ||
|
||||
strlen(buf) < 1)
|
||||
continue;
|
||||
|
||||
if (fputs(buf, keyfp) < 0) {
|
||||
log_debug("%s: failed to write public key",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(keyfp);
|
||||
keyfp = NULL;
|
||||
|
||||
az->az_pubkeyval = keybuf;
|
||||
|
||||
done:
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
if (keyfp != NULL) {
|
||||
fclose(keyfp);
|
||||
free(keybuf);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct httpget *
|
||||
azure_request(struct system_config *sc, struct xml *xml, const char *path,
|
||||
const void *post, size_t postsz, struct httphead **head)
|
||||
{
|
||||
struct azure_config *az = sc->sc_priv;
|
||||
struct httpget *g = NULL;
|
||||
struct httphead **reqhead = NULL;
|
||||
int i;
|
||||
|
||||
if (xml != NULL && xml_init(xml) != 0)
|
||||
return (NULL);
|
||||
|
||||
for (i = 0; head != NULL && head[i] != NULL; i++)
|
||||
;
|
||||
if ((reqhead = calloc(i + 3, sizeof(struct httphead *))) == NULL) {
|
||||
log_debug("%s: head", __func__);
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; head != NULL && head[i] != NULL; i++)
|
||||
reqhead[i] = head[i];
|
||||
reqhead[i++] = &(struct httphead){ "x-ms-agent-name", "cloud-agent" };
|
||||
reqhead[i++] = &(struct httphead){ "x-ms-version", az->az_apiversion };
|
||||
reqhead[i++] = NULL;
|
||||
|
||||
g = http_get(&sc->sc_addr, 1,
|
||||
sc->sc_endpoint, 80, path, post, postsz, reqhead);
|
||||
if (g == NULL || g->code != 200) {
|
||||
log_debug("%s: invalid response", __func__);
|
||||
goto fail;
|
||||
}
|
||||
free(reqhead);
|
||||
|
||||
if (xml == NULL) {
|
||||
if (log_getverbose() > 2)
|
||||
fwrite(g->bodypart, g->bodypartsz, 1, stderr);
|
||||
return (g);
|
||||
}
|
||||
|
||||
if (g->bodypartsz < 1 ||
|
||||
xml_parse_buffer(xml, g->bodypart, g->bodypartsz) != 0) {
|
||||
log_debug("%s: xml", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (log_getverbose() > 2)
|
||||
xml_print(xml, TAILQ_FIRST(&xml->ox_root), 0, stderr);
|
||||
|
||||
return (g);
|
||||
|
||||
fail:
|
||||
xml_free(xml);
|
||||
if (reqhead != NULL)
|
||||
free(reqhead);
|
||||
if (g != NULL)
|
||||
http_get_free(g);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
azure_versions(struct system_config *sc)
|
||||
{
|
||||
struct azure_config *az = sc->sc_priv;
|
||||
struct httpget *g;
|
||||
struct xmlelem *xe, *xv;
|
||||
int ret = -1;
|
||||
struct xml xml;
|
||||
|
||||
if ((g = azure_request(sc, &xml, "/?comp=versions",
|
||||
NULL, 0, NULL)) == NULL)
|
||||
goto done;
|
||||
|
||||
if ((xe = xml_findl(&xml.ox_root,
|
||||
"Versions", "Supported", NULL)) == NULL) {
|
||||
log_debug("%s: unexpected xml document", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(xv, &xe->xe_head, xe_entry) {
|
||||
if (strcmp("Version", xv->xe_tag) == 0 &&
|
||||
strcmp(xv->xe_data, az->az_apiversion) == 0) {
|
||||
/* success! */
|
||||
log_debug("%s: API version %s", __func__, xv->xe_data);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
xml_free(&xml);
|
||||
http_get_free(g);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
azure_goalstate(struct system_config *sc)
|
||||
{
|
||||
struct azure_config *az = sc->sc_priv;
|
||||
struct httpget *g;
|
||||
struct xmlelem *xe;
|
||||
int ret = -1;
|
||||
struct xml xml;
|
||||
const char *errstr = NULL;
|
||||
|
||||
if ((g = azure_request(sc, &xml, "/machine/?comp=goalstate",
|
||||
NULL, 0, NULL)) == NULL)
|
||||
goto done;
|
||||
|
||||
if ((xe = xml_findl(&xml.ox_root,
|
||||
"GoalState", "Version", NULL)) == NULL ||
|
||||
strcmp(xe->xe_data, az->az_apiversion) != 0) {
|
||||
log_debug("%s: unexpected API version", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xml.ox_root,
|
||||
"GoalState", "Incarnation", NULL)) == NULL) {
|
||||
log_debug("%s: unexpected incarnation", __func__);
|
||||
goto done;
|
||||
}
|
||||
az->az_incarnation = strtonum(xe->xe_data, 1, INT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
log_debug("%s: unexpected incarnation: %s", __func__, errstr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xml.ox_root,
|
||||
"GoalState", "Container", "ContainerId", NULL)) == NULL ||
|
||||
(az->az_container = strdup(xe->xe_data)) == NULL) {
|
||||
log_debug("%s: unexpected container id", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xml.ox_root,
|
||||
"GoalState", "Container", "RoleInstanceList",
|
||||
"RoleInstance", "InstanceId", NULL)) == NULL ||
|
||||
(sc->sc_instance = strdup(xe->xe_data)) == NULL) {
|
||||
log_debug("%s: unexpected instance id", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
log_debug("%s: container %s instance %s incarnation %d", __func__,
|
||||
az->az_container, sc->sc_instance, az->az_incarnation);
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
xml_free(&xml);
|
||||
http_get_free(g);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
azure_certificates(struct system_config *sc)
|
||||
{
|
||||
struct azure_config *az = sc->sc_priv;
|
||||
struct httpget *g;
|
||||
struct httphead *reqhead[3];
|
||||
int ret = -1;
|
||||
char *req = NULL;
|
||||
char tmp1[32], tmp2[32];
|
||||
struct xml xml;
|
||||
struct xmlelem *xe, *data;
|
||||
int fd;
|
||||
|
||||
memset(tmp1, 0, sizeof(tmp1));
|
||||
memset(tmp2, 0, sizeof(tmp2));
|
||||
|
||||
reqhead[0] = &(struct httphead){ "x-ms-cipher-name", "DES_EDE3_CBC" };
|
||||
reqhead[1] = &(struct httphead){
|
||||
"x-ms-guest-agent-public-x509-cert", az->az_pubkeyval
|
||||
};
|
||||
reqhead[2] = NULL;
|
||||
|
||||
if (asprintf(&req, "/machine/%s/%s?comp=certificates&incarnation=%d",
|
||||
az->az_container, sc->sc_instance, az->az_incarnation) == -1)
|
||||
return (-1);
|
||||
|
||||
g = azure_request(sc, &xml, req, NULL, 0, reqhead);
|
||||
|
||||
http_get_free(g);
|
||||
free(req);
|
||||
req = NULL;
|
||||
|
||||
/* certificates are optional and only needed w/o password auth */
|
||||
if (g == NULL)
|
||||
return (0);
|
||||
|
||||
if ((xe = xml_findl(&xml.ox_root,
|
||||
"CertificateFile", "Version", NULL)) == NULL ||
|
||||
strcmp(xe->xe_data, az->az_apiversion) != 0) {
|
||||
log_debug("%s: unexpected API version", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xml.ox_root,
|
||||
"CertificateFile", "Format", NULL)) == NULL ||
|
||||
strcmp(xe->xe_data, "Pkcs7BlobWithPfxContents") != 0) {
|
||||
log_debug("%s: unexpected format", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((data = xml_findl(&xml.ox_root,
|
||||
"CertificateFile", "Data", NULL)) == NULL) {
|
||||
log_debug("%s: no data", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Write CMS blob to temporary file */
|
||||
strlcpy(tmp1, "/tmp/azure-cms.XXXXXXXX", sizeof(tmp1));
|
||||
if ((fd = mkstemp(tmp1)) == -1) {
|
||||
log_debug("%s: failed to write data", __func__);
|
||||
goto done;
|
||||
}
|
||||
dprintf(fd, "MIME-Version: 1.0\n"
|
||||
"Content-Disposition: attachment; filename=\"smime.p7m\"\n"
|
||||
"Content-Type: application/pkcs7-mime;"
|
||||
" smime-type=enveloped-data; name=\"smime.p7m\"\n"
|
||||
"Content-Transfer-Encoding: base64\n"
|
||||
"\n%s",
|
||||
data->xe_data);
|
||||
close(fd);
|
||||
|
||||
strlcpy(tmp2, "/tmp/azure-pkcs12.XXXXXXXX", sizeof(tmp2));
|
||||
if ((fd = mkstemp(tmp2)) == -1) {
|
||||
log_debug("%s: failed to write data", __func__);
|
||||
goto done;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
fd = disable_output(sc, STDERR_FILENO);
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
/*
|
||||
* XXX Now comes the part that needs CMS which is only
|
||||
* XXX present in OpenSSL but got removed from LibreSSL.
|
||||
*/
|
||||
log_debug("%s: running openssl cms", __func__);
|
||||
if (shell("/usr/local/bin/eopenssl", "cms", /* )) */
|
||||
#else
|
||||
if (shell("/usr/local/bin/cms",
|
||||
#endif
|
||||
"-decrypt", "-inkey", az->az_privkey, "-des3",
|
||||
"-in", tmp1, "-out", tmp2, NULL) != 0) {
|
||||
enable_output(sc, STDERR_FILENO, fd);
|
||||
log_debug("%s: failed to decrypt CMS blob", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
unlink(tmp1);
|
||||
|
||||
/* Decrypt PKCS12 blob (now with LibreSSL) */
|
||||
if (shell("openssl", "pkcs12",
|
||||
"-nodes", "-password", "pass:",
|
||||
"-in", tmp2, "-out", az->az_certs, NULL) != 0) {
|
||||
enable_output(sc, STDERR_FILENO, fd);
|
||||
log_debug("%s: failed to decrypt PKCS12 blob", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
unlink(tmp2);
|
||||
|
||||
enable_output(sc, STDERR_FILENO, fd);
|
||||
|
||||
/*
|
||||
* XXX the following could be done using libcrypto directly
|
||||
*/
|
||||
ret = azure_getpubkeys(sc);
|
||||
|
||||
done:
|
||||
unlink(tmp1);
|
||||
unlink(tmp2);
|
||||
xml_free(&xml);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
azure_getpubkeys(struct system_config *sc)
|
||||
{
|
||||
struct azure_config *az = sc->sc_priv;
|
||||
char buf[BUFSIZ];
|
||||
char *in = NULL, *out = NULL, *p, *v;
|
||||
FILE *fp;
|
||||
int ret = -1;
|
||||
FILE *infp = NULL;
|
||||
char *inbuf;
|
||||
size_t inbufsz;
|
||||
|
||||
if ((fp = fopen(az->az_certs, "r")) == NULL) {
|
||||
log_debug("%s: failed to read certificates", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read all certificates */
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
buf[strcspn(buf, "\r\n")] = '\0';
|
||||
|
||||
if (strcmp("-----BEGIN CERTIFICATE-----", buf) == 0) {
|
||||
if ((infp = open_memstream(&inbuf, &inbufsz)) == NULL) {
|
||||
log_debug("%s: failed to write cert", __func__);
|
||||
goto done;
|
||||
}
|
||||
} else if (infp == NULL)
|
||||
continue;
|
||||
|
||||
fprintf(infp, "%s\n", buf);
|
||||
|
||||
if (strcmp("-----END CERTIFICATE-----", buf) == 0) {
|
||||
fclose(infp);
|
||||
infp = NULL;
|
||||
|
||||
/* Convert certificate into public key */
|
||||
if (shellout(inbuf, &in,
|
||||
"openssl", "x509", "-fingerprint", "-pubkey",
|
||||
"-noout", NULL) != 0) {
|
||||
log_debug("%s: could not get public key",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
free(inbuf);
|
||||
inbuf = NULL;
|
||||
|
||||
/* Convert public key into SSH key */
|
||||
if (shellout(in, &out,
|
||||
"ssh-keygen", "-i", "-m", "PKCS8",
|
||||
"-f", "/dev/stdin", NULL) == -1) {
|
||||
log_debug("%s: could not get ssh key",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Get public key fingerprint */
|
||||
if ((p = strstr(in, "Fingerprint=")) == NULL) {
|
||||
log_debug("%s: could not get fingerprint",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
p[strcspn(p, "\r\n")] = '\0';
|
||||
p += strlen("Fingerprint=");
|
||||
|
||||
/* Strip colons */
|
||||
for (v = p + strlen(p); v != p; v--)
|
||||
if (*v == ':')
|
||||
memmove(v, v + 1, strlen(v));
|
||||
|
||||
if (agent_setpubkey(sc, out, p) > 0)
|
||||
log_debug("%s: public key %s", __func__, p);
|
||||
|
||||
free(in);
|
||||
in = NULL;
|
||||
free(out);
|
||||
out = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
free(inbuf);
|
||||
free(in);
|
||||
free(out);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
azure_reporthealth(struct system_config *sc, const char *message)
|
||||
{
|
||||
struct azure_config *az = sc->sc_priv;
|
||||
struct httpget *g = NULL;
|
||||
struct httphead *httph, *reqhead[2];
|
||||
const char *errstr = NULL;
|
||||
size_t httphsz, i;
|
||||
int ret = -1;
|
||||
char *req;
|
||||
int reqsz;
|
||||
const char *state;
|
||||
|
||||
reqhead[0] = &(struct httphead){
|
||||
"Content-Type", "text/xml; charset=utf-8"
|
||||
};
|
||||
reqhead[1] = NULL;
|
||||
|
||||
if (strcmp("Ready", message) == 0) {
|
||||
state = "<State>Ready</State>";
|
||||
} else {
|
||||
state =
|
||||
"<State>NotReady</State>\n"
|
||||
"<Details>\n"
|
||||
"<SubStatus>Provisioning</SubStatus>\n"
|
||||
"<Description>Starting</Description>\n"
|
||||
"</Details>";
|
||||
}
|
||||
|
||||
reqsz = asprintf(&req,
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
"<Health xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n"
|
||||
"<GoalStateIncarnation>%u</GoalStateIncarnation>\n"
|
||||
"<Container>\n"
|
||||
"<ContainerId>%s</ContainerId>\n"
|
||||
"<RoleInstanceList>\n"
|
||||
"<Role>\n"
|
||||
"<InstanceId>%s</InstanceId>\n"
|
||||
"<Health>%s</Health>\n"
|
||||
"</Role>\n"
|
||||
"</RoleInstanceList>\n"
|
||||
"</Container>\n"
|
||||
"</Health>\n",
|
||||
az->az_incarnation,
|
||||
az->az_container,
|
||||
sc->sc_instance,
|
||||
state);
|
||||
if (reqsz == -1)
|
||||
goto done;
|
||||
|
||||
if ((g = azure_request(sc, NULL, "/machine/?comp=health",
|
||||
req, reqsz, reqhead)) == NULL)
|
||||
goto done;
|
||||
|
||||
httph = http_head_parse(g->http, g->xfer, &httphsz);
|
||||
|
||||
for (i = 0; i < httphsz; i++) {
|
||||
if (strcmp(httph[i].key,
|
||||
"x-ms-latest-goal-state-incarnation-number") == 0) {
|
||||
az->az_incarnation =
|
||||
strtonum(httph[i].val, 1, INT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
log_debug("%s: unexpected incarnation: %s",
|
||||
__func__, errstr);
|
||||
goto done;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
log_debug("%s: %s, incarnation %u", __func__,
|
||||
message, az->az_incarnation);
|
||||
|
||||
done:
|
||||
http_get_free(g);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
azure_getovfenv(struct system_config *sc)
|
||||
{
|
||||
struct xml xml;
|
||||
struct xmlelem *xp, *xe, *xk, *xv;
|
||||
const char *sshfp, *sshval;
|
||||
int mount = 0, ret = -1, fd = -1;
|
||||
FILE *fp;
|
||||
|
||||
/* try to mount the cdrom */
|
||||
if (shell("mount", "-r", sc->sc_cdrom, "/mnt", NULL) == 0) {
|
||||
log_debug("%s: mounted %s", __func__, sc->sc_cdrom);
|
||||
mount = 1;
|
||||
}
|
||||
|
||||
if (xml_init(&xml) != 0) {
|
||||
log_debug("%s: xml", __func__);
|
||||
goto done;
|
||||
}
|
||||
xml_parse(&xml, "/mnt/ovf-env.xml");
|
||||
|
||||
/* unmount if we mounted the cdrom before */
|
||||
if (mount && shell("umount", "/mnt", NULL) == 0) {
|
||||
log_debug("%s: unmounted %s", __func__, sc->sc_cdrom);
|
||||
}
|
||||
|
||||
if ((xp = xml_findl(&xml.ox_root,
|
||||
"Environment", "wa:ProvisioningSection",
|
||||
"LinuxProvisioningConfigurationSet", NULL)) == NULL) {
|
||||
log_debug("%s: could not find OVF structure", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xp->xe_head,
|
||||
"SSH", "PublicKeys", NULL)) != NULL) {
|
||||
/* Find all (optional) SSH keys */
|
||||
TAILQ_FOREACH(xk, &xe->xe_head, xe_entry) {
|
||||
if (strcasecmp(xk->xe_tag, "PublicKey") != 0)
|
||||
continue;
|
||||
|
||||
sshfp = sshval = NULL;
|
||||
|
||||
if ((xv = xml_findl(&xk->xe_head,
|
||||
"Fingerprint", NULL)) != NULL)
|
||||
sshfp = xv->xe_data;
|
||||
if ((xv = xml_findl(&xk->xe_head,
|
||||
"Value", NULL)) != NULL)
|
||||
sshval = xv->xe_data;
|
||||
|
||||
if (agent_addpubkey(sc, sshval, sshfp) != 0)
|
||||
log_warnx("failed to add ssh pubkey");
|
||||
}
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xp->xe_head, "HostName", NULL)) != NULL) {
|
||||
if ((sc->sc_hostname = strdup(xe->xe_data)) == NULL) {
|
||||
log_debug("%s: hostname failed", __func__);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xp->xe_head, "UserName", NULL)) != NULL) {
|
||||
free(sc->sc_username);
|
||||
if ((sc->sc_username = strdup(xe->xe_data)) == NULL) {
|
||||
log_debug("%s: username failed", __func__);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((xe = xml_findl(&xp->xe_head, "UserPassword", NULL)) != NULL) {
|
||||
if ((sc->sc_password = calloc(1, 128)) == NULL ||
|
||||
crypt_newhash(xe->xe_data, "bcrypt,a",
|
||||
sc->sc_password, 128) != 0) {
|
||||
log_debug("%s: password failed", __func__);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((fd = open(sc->sc_ovfenv, O_WRONLY|O_CREAT|O_TRUNC, 0600)) == -1 ||
|
||||
(fp = fdopen(fd, "w")) == NULL) {
|
||||
log_debug("%s: failed to open %s", __func__, sc->sc_ovfenv);
|
||||
goto done;
|
||||
}
|
||||
|
||||
xml_print(&xml, TAILQ_FIRST(&xml.ox_root), 0, fp);
|
||||
fclose(fp);
|
||||
|
||||
log_debug("%s: wrote %s", __func__, sc->sc_ovfenv);
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
xml_free(&xml);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
azure_getendpoint(struct system_config *sc)
|
||||
{
|
||||
char path[PATH_MAX], buf[BUFSIZ], *ep = NULL;
|
||||
int a[4];
|
||||
FILE *fp;
|
||||
|
||||
if ((size_t)snprintf(path, sizeof(path), "/var/db/dhclient.leases.%s",
|
||||
sc->sc_interface) >= sizeof(path)) {
|
||||
log_debug("%s: invalid path", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((fp = fopen(path, "r")) == NULL) {
|
||||
log_debug("%s: failed to open %s", __func__, path);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
buf[strcspn(buf, ";\n")] = '\0';
|
||||
|
||||
/* Find last occurence of option-245 */
|
||||
if (sscanf(buf, " option option-245 %x:%x:%x:%x",
|
||||
&a[0], &a[1], &a[2], &a[3]) == 4) {
|
||||
free(ep);
|
||||
if (asprintf(&ep, "%d.%d.%d.%d",
|
||||
a[0], a[1], a[2], a[3]) == -1) {
|
||||
log_debug("%s: asprintf", __func__);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (ep == NULL) {
|
||||
log_debug("%s: endpoint not found", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sc->sc_endpoint = ep;
|
||||
sc->sc_addr.ip = sc->sc_endpoint;
|
||||
sc->sc_addr.family = 4;
|
||||
|
||||
log_debug("%s: %s", __func__, ep);
|
||||
|
||||
return (0);
|
||||
}
|
117
agent/cloudinit.c
Normal file
117
agent/cloudinit.c
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "http.h"
|
||||
#include "xml.h"
|
||||
|
||||
static int cloudinit_fetch(struct system_config *);
|
||||
static char *cloudinit_get(struct system_config *, const char *, size_t *);
|
||||
|
||||
int
|
||||
ec2(struct system_config *sc)
|
||||
{
|
||||
if ((sc->sc_username = strdup("ec2-user")) == NULL ||
|
||||
(sc->sc_endpoint = strdup("169.254.169.254")) == NULL) {
|
||||
log_warnx("failed to set defaults");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (cloudinit_fetch(sc));
|
||||
}
|
||||
|
||||
int
|
||||
cloudinit(struct system_config *sc)
|
||||
{
|
||||
/* XXX get endpoint from DHCP lease file */
|
||||
if ((sc->sc_username = strdup("puffy")) == NULL ||
|
||||
(sc->sc_endpoint = strdup("169.254.169.254")) == NULL) {
|
||||
log_warnx("failed to set defaults");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (cloudinit_fetch(sc));
|
||||
}
|
||||
|
||||
static char *
|
||||
cloudinit_get(struct system_config *sc, const char *path, size_t *strsz)
|
||||
{
|
||||
struct httpget *g = NULL;
|
||||
char *str = NULL;
|
||||
|
||||
log_debug("%s: %s", __func__, path);
|
||||
|
||||
g = http_get(&sc->sc_addr, 1,
|
||||
sc->sc_endpoint, 80, path, NULL, 0, NULL);
|
||||
if (g != NULL && g->code == 200 && g->bodypartsz > 0) {
|
||||
if ((str = calloc(1, g->bodypartsz + 1)) != NULL) {
|
||||
memcpy(str, g->bodypart, g->bodypartsz);
|
||||
if (strsz != NULL)
|
||||
*strsz = g->bodypartsz;
|
||||
}
|
||||
}
|
||||
http_get_free(g);
|
||||
|
||||
return (str);
|
||||
}
|
||||
|
||||
static int
|
||||
cloudinit_fetch(struct system_config *sc)
|
||||
{
|
||||
int ret = 0;
|
||||
char *str = NULL;
|
||||
|
||||
sc->sc_addr.ip = sc->sc_endpoint;
|
||||
sc->sc_addr.family = 4;
|
||||
|
||||
/* hostname */
|
||||
if ((sc->sc_instance = cloudinit_get(sc,
|
||||
"/latest/meta-data/instance-id", NULL)) == NULL)
|
||||
goto fail;
|
||||
|
||||
/* hostname */
|
||||
if ((sc->sc_hostname = cloudinit_get(sc,
|
||||
"/latest/meta-data/local-hostname", NULL)) == NULL)
|
||||
goto fail;
|
||||
|
||||
/* pubkey */
|
||||
if ((str = cloudinit_get(sc,
|
||||
"/latest/meta-data/public-keys/0/openssh-key", NULL)) == NULL)
|
||||
goto fail;
|
||||
if (agent_addpubkey(sc, str, NULL) != 0)
|
||||
goto fail;
|
||||
|
||||
/* userdata */
|
||||
if ((sc->sc_userdata = cloudinit_get(sc,
|
||||
"/latest/user-data", &sc->sc_userdatalen)) == NULL)
|
||||
goto fail;
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
free(str);
|
||||
return (ret);
|
||||
}
|
818
agent/http.c
Normal file
818
agent/http.c
Normal file
|
@ -0,0 +1,818 @@
|
|||
/* $Id: http.c,v 1.20 2017/03/26 18:41:02 deraadt Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <tls.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "http.h"
|
||||
|
||||
#define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
|
||||
|
||||
/*
|
||||
* A buffer for transferring HTTP/S data.
|
||||
*/
|
||||
struct httpxfer {
|
||||
char *hbuf; /* header transfer buffer */
|
||||
size_t hbufsz; /* header buffer size */
|
||||
int headok; /* header has been parsed */
|
||||
char *bbuf; /* body transfer buffer */
|
||||
size_t bbufsz; /* body buffer size */
|
||||
int bodyok; /* body has been parsed */
|
||||
char *headbuf; /* lookaside buffer for headers */
|
||||
struct httphead *head; /* parsed headers */
|
||||
size_t headsz; /* number of headers */
|
||||
};
|
||||
|
||||
/*
|
||||
* An HTTP/S connection object.
|
||||
*/
|
||||
struct http {
|
||||
int fd; /* connected socket */
|
||||
short port; /* port number */
|
||||
struct source src; /* endpoint (raw) host */
|
||||
char *path; /* path to request */
|
||||
char *host; /* name of endpoint host */
|
||||
struct tls *ctx; /* if TLS */
|
||||
writefp writer; /* write function */
|
||||
readfp reader; /* read function */
|
||||
};
|
||||
|
||||
struct tls_config *tlscfg;
|
||||
|
||||
static ssize_t
|
||||
dosysread(char *buf, size_t sz, const struct http *http)
|
||||
{
|
||||
ssize_t rc;
|
||||
|
||||
rc = read(http->fd, buf, sz);
|
||||
if (rc < 0)
|
||||
warn("%s: read", http->src.ip);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dosyswrite(const void *buf, size_t sz, const struct http *http)
|
||||
{
|
||||
ssize_t rc;
|
||||
|
||||
rc = write(http->fd, buf, sz);
|
||||
if (rc < 0)
|
||||
warn("%s: write", http->src.ip);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dotlsread(char *buf, size_t sz, const struct http *http)
|
||||
{
|
||||
ssize_t rc;
|
||||
|
||||
do {
|
||||
rc = tls_read(http->ctx, buf, sz);
|
||||
} while (rc == TLS_WANT_POLLIN || rc == TLS_WANT_POLLOUT);
|
||||
|
||||
if (rc < 0)
|
||||
warnx("%s: tls_read: %s", http->src.ip,
|
||||
tls_error(http->ctx));
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dotlswrite(const void *buf, size_t sz, const struct http *http)
|
||||
{
|
||||
ssize_t rc;
|
||||
|
||||
do {
|
||||
rc = tls_write(http->ctx, buf, sz);
|
||||
} while (rc == TLS_WANT_POLLIN || rc == TLS_WANT_POLLOUT);
|
||||
|
||||
if (rc < 0)
|
||||
warnx("%s: tls_write: %s", http->src.ip,
|
||||
tls_error(http->ctx));
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
http_init()
|
||||
{
|
||||
if (tlscfg != NULL)
|
||||
return 0;
|
||||
|
||||
if (tls_init() == -1) {
|
||||
warn("tls_init");
|
||||
goto err;
|
||||
}
|
||||
|
||||
tlscfg = tls_config_new();
|
||||
if (tlscfg == NULL) {
|
||||
warn("tls_config_new");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tls_config_set_ca_file(tlscfg, DEFAULT_CA_FILE) == -1) {
|
||||
warn("tls_config_set_ca_file: %s", tls_config_error(tlscfg));
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
tls_config_free(tlscfg);
|
||||
tlscfg = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
http_read(char *buf, size_t sz, const struct http *http)
|
||||
{
|
||||
ssize_t ssz, xfer;
|
||||
|
||||
xfer = 0;
|
||||
do {
|
||||
if ((ssz = http->reader(buf, sz, http)) < 0)
|
||||
return -1;
|
||||
if (ssz == 0)
|
||||
break;
|
||||
xfer += ssz;
|
||||
sz -= ssz;
|
||||
buf += ssz;
|
||||
} while (ssz > 0 && sz > 0);
|
||||
|
||||
return xfer;
|
||||
}
|
||||
|
||||
static int
|
||||
http_write(const char *buf, size_t sz, const struct http *http)
|
||||
{
|
||||
ssize_t ssz, xfer;
|
||||
|
||||
xfer = sz;
|
||||
while (sz > 0) {
|
||||
if ((ssz = http->writer(buf, sz, http)) < 0)
|
||||
return -1;
|
||||
sz -= ssz;
|
||||
buf += (size_t)ssz;
|
||||
}
|
||||
return xfer;
|
||||
}
|
||||
|
||||
void
|
||||
http_disconnect(struct http *http)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (http->ctx != NULL) {
|
||||
/* TLS connection. */
|
||||
do {
|
||||
rc = tls_close(http->ctx);
|
||||
} while (rc == TLS_WANT_POLLIN || rc == TLS_WANT_POLLOUT);
|
||||
|
||||
if (rc < 0)
|
||||
warnx("%s: tls_close: %s", http->src.ip,
|
||||
tls_error(http->ctx));
|
||||
|
||||
tls_free(http->ctx);
|
||||
}
|
||||
if (http->fd != -1) {
|
||||
if (close(http->fd) == -1)
|
||||
warn("%s: close", http->src.ip);
|
||||
}
|
||||
|
||||
http->fd = -1;
|
||||
http->ctx = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
http_free(struct http *http)
|
||||
{
|
||||
|
||||
if (http == NULL)
|
||||
return;
|
||||
http_disconnect(http);
|
||||
free(http->host);
|
||||
free(http->path);
|
||||
free(http->src.ip);
|
||||
free(http);
|
||||
}
|
||||
|
||||
struct http *
|
||||
http_alloc(const struct source *addrs, size_t addrsz,
|
||||
const char *host, short port, const char *path)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
int family, fd, c;
|
||||
socklen_t len;
|
||||
size_t cur, i = 0;
|
||||
struct http *http;
|
||||
|
||||
/* Do this while we still have addresses to connect. */
|
||||
again:
|
||||
if (i == addrsz)
|
||||
return NULL;
|
||||
cur = i++;
|
||||
|
||||
/* Convert to PF_INET or PF_INET6 address from string. */
|
||||
|
||||
memset(&ss, 0, sizeof(struct sockaddr_storage));
|
||||
|
||||
if (addrs[cur].family == 4) {
|
||||
family = PF_INET;
|
||||
((struct sockaddr_in *)&ss)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)&ss)->sin_port = htons(port);
|
||||
c = inet_pton(AF_INET, addrs[cur].ip,
|
||||
&((struct sockaddr_in *)&ss)->sin_addr);
|
||||
len = sizeof(struct sockaddr_in);
|
||||
} else if (addrs[cur].family == 6) {
|
||||
family = PF_INET6;
|
||||
((struct sockaddr_in6 *)&ss)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)&ss)->sin6_port = htons(port);
|
||||
c = inet_pton(AF_INET6, addrs[cur].ip,
|
||||
&((struct sockaddr_in6 *)&ss)->sin6_addr);
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
warnx("%s: unknown family", addrs[cur].ip);
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (c < 0) {
|
||||
warn("%s: inet_ntop", addrs[cur].ip);
|
||||
goto again;
|
||||
} else if (c == 0) {
|
||||
warnx("%s: inet_ntop", addrs[cur].ip);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Create socket and connect. */
|
||||
|
||||
fd = socket(family, SOCK_STREAM, 0);
|
||||
if (fd == -1) {
|
||||
warn("%s: socket", addrs[cur].ip);
|
||||
goto again;
|
||||
} else if (connect(fd, (struct sockaddr *)&ss, len) == -1) {
|
||||
warn("%s: connect", addrs[cur].ip);
|
||||
close(fd);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Allocate the communicator. */
|
||||
|
||||
http = calloc(1, sizeof(struct http));
|
||||
if (http == NULL) {
|
||||
warn("calloc");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
http->fd = fd;
|
||||
http->port = port;
|
||||
http->src.family = addrs[cur].family;
|
||||
http->src.ip = strdup(addrs[cur].ip);
|
||||
http->host = strdup(host);
|
||||
http->path = strdup(path);
|
||||
if (http->src.ip == NULL || http->host == NULL || http->path == NULL) {
|
||||
warn("strdup");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If necessary, do our TLS setup. */
|
||||
|
||||
if (port != 443) {
|
||||
http->writer = dosyswrite;
|
||||
http->reader = dosysread;
|
||||
return http;
|
||||
}
|
||||
|
||||
http->writer = dotlswrite;
|
||||
http->reader = dotlsread;
|
||||
|
||||
if ((http->ctx = tls_client()) == NULL) {
|
||||
warn("tls_client");
|
||||
goto err;
|
||||
} else if (tls_configure(http->ctx, tlscfg) == -1) {
|
||||
warnx("%s: tls_configure: %s",
|
||||
http->src.ip, tls_error(http->ctx));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tls_connect_socket(http->ctx, http->fd, http->host) != 0) {
|
||||
warnx("%s: tls_connect_socket: %s, %s", http->src.ip,
|
||||
http->host, tls_error(http->ctx));
|
||||
goto err;
|
||||
}
|
||||
|
||||
return http;
|
||||
err:
|
||||
http_free(http);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
http_head_write(struct httphead **head, const struct http *http)
|
||||
{
|
||||
char *req = NULL;
|
||||
int i, c;
|
||||
|
||||
if (head == NULL)
|
||||
return (0);
|
||||
|
||||
for (i = 0; head[i] != NULL && head[i]->key != NULL; i++) {
|
||||
/* Append terminating \r\n after last header line */
|
||||
c = asprintf(&req, "%s: %s\r\n%s", head[i]->key, head[i]->val,
|
||||
head[i + 1] == NULL ? "\r\n" : "");
|
||||
if (!http_write(req, c, http)) {
|
||||
free(req);
|
||||
return (-1);
|
||||
}
|
||||
free(req);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct httpxfer *
|
||||
http_open(const struct http *http, const void *p, size_t psz,
|
||||
struct httphead **reqhead)
|
||||
{
|
||||
char *req;
|
||||
int c;
|
||||
struct httpxfer *trans;
|
||||
|
||||
if (p == NULL) {
|
||||
c = asprintf(&req,
|
||||
"GET %s HTTP/1.0\r\n"
|
||||
"Host: %s\r\n%s",
|
||||
http->path, http->host,
|
||||
reqhead != NULL ? "" : "\r\n");
|
||||
} else {
|
||||
c = asprintf(&req,
|
||||
"POST %s HTTP/1.0\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Content-Length: %zu\r\n%s",
|
||||
http->path, http->host, psz,
|
||||
reqhead != NULL ? "" : "\r\n");
|
||||
}
|
||||
if (c == -1) {
|
||||
warn("asprintf");
|
||||
return NULL;
|
||||
} else if (!http_write(req, c, http)) {
|
||||
free(req);
|
||||
return NULL;
|
||||
} else if (http_head_write(reqhead, http) != 0) {
|
||||
free(req);
|
||||
return NULL;
|
||||
} else if (p != NULL && !http_write(p, psz, http)) {
|
||||
free(req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(req);
|
||||
|
||||
trans = calloc(1, sizeof(struct httpxfer));
|
||||
if (trans == NULL)
|
||||
warn("calloc");
|
||||
return trans;
|
||||
}
|
||||
|
||||
void
|
||||
http_close(struct httpxfer *x)
|
||||
{
|
||||
|
||||
if (x == NULL)
|
||||
return;
|
||||
free(x->hbuf);
|
||||
free(x->bbuf);
|
||||
free(x->headbuf);
|
||||
free(x->head);
|
||||
free(x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the HTTP body from the wire.
|
||||
* If invoked multiple times, this will return the same pointer with the
|
||||
* same data (or NULL, if the original invocation returned NULL).
|
||||
* Returns NULL if read or allocation errors occur.
|
||||
* You must not free the returned pointer.
|
||||
*/
|
||||
char *
|
||||
http_body_read(const struct http *http, struct httpxfer *trans, size_t *sz)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
ssize_t ssz;
|
||||
void *pp;
|
||||
size_t szp;
|
||||
|
||||
if (sz == NULL)
|
||||
sz = &szp;
|
||||
|
||||
/* Have we already parsed this? */
|
||||
|
||||
if (trans->bodyok > 0) {
|
||||
*sz = trans->bbufsz;
|
||||
return trans->bbuf;
|
||||
} else if (trans->bodyok < 0)
|
||||
return NULL;
|
||||
|
||||
*sz = 0;
|
||||
trans->bodyok = -1;
|
||||
|
||||
do {
|
||||
/* If less than sizeof(buf), at EOF. */
|
||||
if ((ssz = http_read(buf, sizeof(buf), http)) < 0)
|
||||
return NULL;
|
||||
else if (ssz == 0)
|
||||
break;
|
||||
pp = recallocarray(trans->bbuf,
|
||||
trans->bbufsz, trans->bbufsz + ssz, 1);
|
||||
if (pp == NULL) {
|
||||
warn("recallocarray");
|
||||
return NULL;
|
||||
}
|
||||
trans->bbuf = pp;
|
||||
memcpy(trans->bbuf + trans->bbufsz, buf, ssz);
|
||||
trans->bbufsz += ssz;
|
||||
} while (ssz == sizeof(buf));
|
||||
|
||||
trans->bodyok = 1;
|
||||
*sz = trans->bbufsz;
|
||||
return trans->bbuf;
|
||||
}
|
||||
|
||||
struct httphead *
|
||||
http_head_get(const char *v, struct httphead *h, size_t hsz)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < hsz; i++) {
|
||||
if (strcmp(h[i].key, v))
|
||||
continue;
|
||||
return &h[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look through the headers and determine our HTTP code.
|
||||
* This will return -1 on failure, otherwise the code.
|
||||
*/
|
||||
int
|
||||
http_head_status(const struct http *http, struct httphead *h, size_t sz)
|
||||
{
|
||||
int rc;
|
||||
unsigned int code;
|
||||
struct httphead *st;
|
||||
|
||||
if ((st = http_head_get("Status", h, sz)) == NULL) {
|
||||
warnx("%s: no status header", http->src.ip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = sscanf(st->val, "%*s %u %*s", &code);
|
||||
if (rc < 0) {
|
||||
warn("sscanf");
|
||||
return -1;
|
||||
} else if (rc != 1) {
|
||||
warnx("%s: cannot convert status header", http->src.ip);
|
||||
return -1;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse headers from the transfer.
|
||||
* Malformed headers are skipped.
|
||||
* A special "Status" header is added for the HTTP status line.
|
||||
* This can only happen once http_head_read has been called with
|
||||
* success.
|
||||
* This can be invoked multiple times: it will only parse the headers
|
||||
* once and after that it will just return the cache.
|
||||
* You must not free the returned pointer.
|
||||
* If the original header parse failed, or if memory allocation fails
|
||||
* internally, this returns NULL.
|
||||
*/
|
||||
struct httphead *
|
||||
http_head_parse(const struct http *http, struct httpxfer *trans, size_t *sz)
|
||||
{
|
||||
size_t hsz, szp;
|
||||
struct httphead *h;
|
||||
char *cp, *ep, *ccp, *buf;
|
||||
|
||||
if (sz == NULL)
|
||||
sz = &szp;
|
||||
|
||||
/*
|
||||
* If we've already parsed the headers, return the
|
||||
* previously-parsed buffer now.
|
||||
* If we have errors on the stream, return NULL now.
|
||||
*/
|
||||
|
||||
if (trans->head != NULL) {
|
||||
*sz = trans->headsz;
|
||||
return trans->head;
|
||||
} else if (trans->headok <= 0)
|
||||
return NULL;
|
||||
|
||||
if ((buf = strdup(trans->hbuf)) == NULL) {
|
||||
warn("strdup");
|
||||
return NULL;
|
||||
}
|
||||
hsz = 0;
|
||||
cp = buf;
|
||||
|
||||
do {
|
||||
if ((cp = strstr(cp, "\r\n")) != NULL)
|
||||
cp += 2;
|
||||
hsz++;
|
||||
} while (cp != NULL);
|
||||
|
||||
/*
|
||||
* Allocate headers, then step through the data buffer, parsing
|
||||
* out headers as we have them.
|
||||
* We know at this point that the buffer is NUL-terminated in
|
||||
* the usual way.
|
||||
*/
|
||||
|
||||
h = calloc(hsz, sizeof(struct httphead));
|
||||
if (h == NULL) {
|
||||
warn("calloc");
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*sz = hsz;
|
||||
hsz = 0;
|
||||
cp = buf;
|
||||
|
||||
do {
|
||||
if ((ep = strstr(cp, "\r\n")) != NULL) {
|
||||
*ep = '\0';
|
||||
ep += 2;
|
||||
}
|
||||
if (hsz == 0) {
|
||||
h[hsz].key = "Status";
|
||||
h[hsz++].val = cp;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip bad headers. */
|
||||
if ((ccp = strchr(cp, ':')) == NULL) {
|
||||
warnx("%s: header without separator", http->src.ip);
|
||||
continue;
|
||||
}
|
||||
|
||||
*ccp++ = '\0';
|
||||
while (isspace((int)*ccp))
|
||||
ccp++;
|
||||
h[hsz].key = cp;
|
||||
h[hsz++].val = ccp;
|
||||
} while ((cp = ep) != NULL);
|
||||
|
||||
trans->headbuf = buf;
|
||||
trans->head = h;
|
||||
trans->headsz = hsz;
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the HTTP headers from the wire.
|
||||
* If invoked multiple times, this will return the same pointer with the
|
||||
* same data (or NULL, if the original invocation returned NULL).
|
||||
* Returns NULL if read or allocation errors occur.
|
||||
* You must not free the returned pointer.
|
||||
*/
|
||||
char *
|
||||
http_head_read(const struct http *http, struct httpxfer *trans, size_t *sz)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
ssize_t ssz;
|
||||
char *ep;
|
||||
void *pp;
|
||||
size_t szp;
|
||||
|
||||
if (sz == NULL)
|
||||
sz = &szp;
|
||||
|
||||
/* Have we already parsed this? */
|
||||
|
||||
if (trans->headok > 0) {
|
||||
*sz = trans->hbufsz;
|
||||
return trans->hbuf;
|
||||
} else if (trans->headok < 0)
|
||||
return NULL;
|
||||
|
||||
*sz = 0;
|
||||
ep = NULL;
|
||||
trans->headok = -1;
|
||||
|
||||
/*
|
||||
* Begin by reading by BUFSIZ blocks until we reach the header
|
||||
* termination marker (two CRLFs).
|
||||
* We might read into our body, but that's ok: we'll copy out
|
||||
* the body parts into our body buffer afterward.
|
||||
*/
|
||||
|
||||
do {
|
||||
/* If less than sizeof(buf), at EOF. */
|
||||
if ((ssz = http_read(buf, sizeof(buf), http)) < 0)
|
||||
return NULL;
|
||||
else if (ssz == 0)
|
||||
break;
|
||||
pp = recallocarray(trans->hbuf,
|
||||
trans->hbufsz, trans->hbufsz + ssz, 1);
|
||||
if (pp == NULL) {
|
||||
warn("recallocarray");
|
||||
return NULL;
|
||||
}
|
||||
trans->hbuf = pp;
|
||||
memcpy(trans->hbuf + trans->hbufsz, buf, ssz);
|
||||
trans->hbufsz += ssz;
|
||||
/* Search for end of headers marker. */
|
||||
ep = memmem(trans->hbuf, trans->hbufsz, "\r\n\r\n", 4);
|
||||
} while (ep == NULL && ssz == sizeof(buf));
|
||||
|
||||
if (ep == NULL) {
|
||||
warnx("%s: partial transfer", http->src.ip);
|
||||
return NULL;
|
||||
}
|
||||
*ep = '\0';
|
||||
|
||||
/*
|
||||
* The header data is invalid if it has any binary characters in
|
||||
* it: check that now.
|
||||
* This is important because we want to guarantee that all
|
||||
* header keys and pairs are properly NUL-terminated.
|
||||
*/
|
||||
|
||||
if (strlen(trans->hbuf) != (uintptr_t)(ep - trans->hbuf)) {
|
||||
warnx("%s: binary data in header", http->src.ip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy remaining buffer into body buffer.
|
||||
*/
|
||||
|
||||
ep += 4;
|
||||
trans->bbufsz = (trans->hbuf + trans->hbufsz) - ep;
|
||||
trans->bbuf = malloc(trans->bbufsz);
|
||||
if (trans->bbuf == NULL) {
|
||||
warn("malloc");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(trans->bbuf, ep, trans->bbufsz);
|
||||
|
||||
trans->headok = 1;
|
||||
*sz = trans->hbufsz;
|
||||
return trans->hbuf;
|
||||
}
|
||||
|
||||
void
|
||||
http_get_free(struct httpget *g)
|
||||
{
|
||||
|
||||
if (g == NULL)
|
||||
return;
|
||||
http_close(g->xfer);
|
||||
http_free(g->http);
|
||||
free(g);
|
||||
}
|
||||
|
||||
struct httpget *
|
||||
http_get(const struct source *addrs, size_t addrsz, const char *domain,
|
||||
short port, const char *path, const void *post, size_t postsz,
|
||||
struct httphead **reqhead)
|
||||
{
|
||||
struct http *h;
|
||||
struct httpxfer *x;
|
||||
struct httpget *g;
|
||||
struct httphead *head;
|
||||
size_t headsz, bodsz, headrsz;
|
||||
int code;
|
||||
char *bod, *headr;
|
||||
|
||||
h = http_alloc(addrs, addrsz, domain, port, path);
|
||||
if (h == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((x = http_open(h, post, postsz, reqhead)) == NULL) {
|
||||
http_free(h);
|
||||
return NULL;
|
||||
} else if ((headr = http_head_read(h, x, &headrsz)) == NULL) {
|
||||
http_close(x);
|
||||
http_free(h);
|
||||
return NULL;
|
||||
} else if ((bod = http_body_read(h, x, &bodsz)) == NULL) {
|
||||
http_close(x);
|
||||
http_free(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
http_disconnect(h);
|
||||
|
||||
if ((head = http_head_parse(h, x, &headsz)) == NULL) {
|
||||
http_close(x);
|
||||
http_free(h);
|
||||
return NULL;
|
||||
} else if ((code = http_head_status(h, head, headsz)) < 0) {
|
||||
http_close(x);
|
||||
http_free(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((g = calloc(1, sizeof(struct httpget))) == NULL) {
|
||||
warn("calloc");
|
||||
http_close(x);
|
||||
http_free(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g->headpart = headr;
|
||||
g->headpartsz = headrsz;
|
||||
g->bodypart = bod;
|
||||
g->bodypartsz = bodsz;
|
||||
g->head = head;
|
||||
g->headsz = headsz;
|
||||
g->code = code;
|
||||
g->xfer = x;
|
||||
g->http = h;
|
||||
return g;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
struct httpget *g;
|
||||
struct httphead *httph;
|
||||
size_t i, httphsz;
|
||||
struct source addrs[2];
|
||||
size_t addrsz;
|
||||
struct httphead *reqhead[3];
|
||||
|
||||
/* This could be allocated ;) */
|
||||
reqhead[0] = &(struct httphead){ "X-Hello", "World" };
|
||||
reqhead[1] = &(struct httphead){ "X-Test", "123" };
|
||||
reqhead[2] = NULL;
|
||||
|
||||
#if 0
|
||||
addrs[0].ip = "127.0.0.1";
|
||||
addrs[0].family = 4;
|
||||
addrsz = 1;
|
||||
#else
|
||||
addrs[0].ip = "2a00:1450:400a:806::2004";
|
||||
addrs[0].family = 6;
|
||||
addrs[1].ip = "193.135.3.123";
|
||||
addrs[1].family = 4;
|
||||
addrsz = 2;
|
||||
#endif
|
||||
|
||||
if (http_init() == -1)
|
||||
errx(EXIT_FAILURE, "http_init");
|
||||
|
||||
#if 0
|
||||
g = http_get(addrs, addrsz, "localhost", 80, "/index.html",
|
||||
NULL, 0, reqhead);
|
||||
#else
|
||||
g = http_get(addrs, addrsz, "www.google.ch", 80, "/index.html",
|
||||
NULL, 0, reqhead);
|
||||
#endif
|
||||
|
||||
if (g == NULL)
|
||||
errx(EXIT_FAILURE, "http_get");
|
||||
|
||||
httph = http_head_parse(g->http, g->xfer, &httphsz);
|
||||
warnx("code: %d", g->code);
|
||||
|
||||
for (i = 0; i < httphsz; i++)
|
||||
warnx("head: [%s]=[%s]", httph[i].key, httph[i].val);
|
||||
|
||||
http_get_free(g);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
#endif
|
93
agent/http.h
Normal file
93
agent/http.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* $Id: http.h,v 1.5 2017/01/25 13:52:53 inoguchi Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef HTTP_H
|
||||
#define HTTP_H
|
||||
|
||||
struct source {
|
||||
int family; /* 4 (PF_INET) or 6 (PF_INET6) */
|
||||
char *ip; /* IPV4 or IPV6 address */
|
||||
};
|
||||
|
||||
struct http;
|
||||
|
||||
/*
|
||||
* Write and read callbacks to allow HTTP and HTTPS.
|
||||
* Both of these return the number of bytes read (or written) or -1 on
|
||||
* failure.
|
||||
* 0 bytes read means that the connection has closed.
|
||||
*/
|
||||
typedef ssize_t (*writefp)(const void *, size_t, const struct http *);
|
||||
typedef ssize_t (*readfp)(char *, size_t, const struct http *);
|
||||
|
||||
/*
|
||||
* HTTP/S header pair.
|
||||
* There's also a cooked-up pair, "Status", with the status code.
|
||||
* Both strings are NUL-terminated.
|
||||
*/
|
||||
struct httphead {
|
||||
const char *key;
|
||||
const char *val;
|
||||
};
|
||||
|
||||
/*
|
||||
* Grab all information from a transfer.
|
||||
* DO NOT free any parts of this, and editing the parts (e.g., changing
|
||||
* the underlying strings) will persist; so in short, don't.
|
||||
* All of these values will be set upon http_get() success.
|
||||
*/
|
||||
struct httpget {
|
||||
struct httpxfer *xfer; /* underlying transfer */
|
||||
struct http *http; /* underlying connection */
|
||||
int code; /* return code */
|
||||
struct httphead *head; /* headers */
|
||||
size_t headsz; /* number of headers */
|
||||
char *headpart; /* header buffer */
|
||||
size_t headpartsz; /* size of headpart */
|
||||
char *bodypart; /* body buffer */
|
||||
size_t bodypartsz; /* size of bodypart */
|
||||
};
|
||||
|
||||
int http_init(void);
|
||||
|
||||
/* Convenience functions. */
|
||||
struct httpget *http_get(const struct source *, size_t,
|
||||
const char *, short, const char *,
|
||||
const void *, size_t, struct httphead **);
|
||||
void http_get_free(struct httpget *);
|
||||
|
||||
/* Allocation and release. */
|
||||
struct http *http_alloc(const struct source *, size_t,
|
||||
const char *, short, const char *);
|
||||
void http_free(struct http *);
|
||||
struct httpxfer *http_open(const struct http *, const void *, size_t,
|
||||
struct httphead **);
|
||||
void http_close(struct httpxfer *);
|
||||
void http_disconnect(struct http *);
|
||||
|
||||
/* Access. */
|
||||
char *http_head_read(const struct http *,
|
||||
struct httpxfer *, size_t *);
|
||||
struct httphead *http_head_parse(const struct http *,
|
||||
struct httpxfer *, size_t *);
|
||||
char *http_body_read(const struct http *,
|
||||
struct httpxfer *, size_t *);
|
||||
int http_head_status(const struct http *,
|
||||
struct httphead *, size_t);
|
||||
struct httphead *http_head_get(const char *,
|
||||
struct httphead *, size_t);
|
||||
|
||||
#endif /* HTTP_H */
|
218
agent/log.c
Normal file
218
agent/log.c
Normal file
|
@ -0,0 +1,218 @@
|
|||
/* $OpenBSD: log.c,v 1.35 2017/03/21 12:06:56 bluhm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
static int debug;
|
||||
static int verbose;
|
||||
const char *log_procname;
|
||||
|
||||
void log_init(int, int);
|
||||
void log_procinit(const char *);
|
||||
void log_setverbose(int);
|
||||
int log_getverbose(void);
|
||||
void log_warn(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void log_warnx(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void log_info(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void log_debug(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void logit(int, const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)));
|
||||
void vlog(int, const char *, va_list)
|
||||
__attribute__((__format__ (printf, 2, 0)));
|
||||
__dead void fatal(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
__dead void fatalx(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
|
||||
void
|
||||
log_init(int n_debug, int facility)
|
||||
{
|
||||
extern char *__progname;
|
||||
|
||||
debug = n_debug;
|
||||
verbose = n_debug;
|
||||
log_procinit(__progname);
|
||||
|
||||
if (!debug)
|
||||
openlog(__progname, LOG_PID | LOG_NDELAY, facility);
|
||||
|
||||
tzset();
|
||||
}
|
||||
|
||||
void
|
||||
log_procinit(const char *procname)
|
||||
{
|
||||
if (procname != NULL)
|
||||
log_procname = procname;
|
||||
}
|
||||
|
||||
void
|
||||
log_setverbose(int v)
|
||||
{
|
||||
verbose = v;
|
||||
}
|
||||
|
||||
int
|
||||
log_getverbose(void)
|
||||
{
|
||||
return (verbose);
|
||||
}
|
||||
|
||||
void
|
||||
logit(int pri, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vlog(pri, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
vlog(int pri, const char *fmt, va_list ap)
|
||||
{
|
||||
char *nfmt;
|
||||
int saved_errno = errno;
|
||||
|
||||
if (debug) {
|
||||
/* best effort in out of mem situations */
|
||||
if (asprintf(&nfmt, "%s\n", fmt) == -1) {
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
} else {
|
||||
vfprintf(stderr, nfmt, ap);
|
||||
free(nfmt);
|
||||
}
|
||||
fflush(stderr);
|
||||
} else
|
||||
vsyslog(pri, fmt, ap);
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
void
|
||||
log_warn(const char *emsg, ...)
|
||||
{
|
||||
char *nfmt;
|
||||
va_list ap;
|
||||
int saved_errno = errno;
|
||||
|
||||
/* best effort to even work in out of memory situations */
|
||||
if (emsg == NULL)
|
||||
logit(LOG_ERR, "%s", strerror(saved_errno));
|
||||
else {
|
||||
va_start(ap, emsg);
|
||||
|
||||
if (asprintf(&nfmt, "%s: %s", emsg,
|
||||
strerror(saved_errno)) == -1) {
|
||||
/* we tried it... */
|
||||
vlog(LOG_ERR, emsg, ap);
|
||||
logit(LOG_ERR, "%s", strerror(saved_errno));
|
||||
} else {
|
||||
vlog(LOG_ERR, nfmt, ap);
|
||||
free(nfmt);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
void
|
||||
log_warnx(const char *emsg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, emsg);
|
||||
vlog(LOG_ERR, emsg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
log_info(const char *emsg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, emsg);
|
||||
vlog(LOG_INFO, emsg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
log_debug(const char *emsg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (verbose > 1) {
|
||||
va_start(ap, emsg);
|
||||
vlog(LOG_DEBUG, emsg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vfatalc(int code, const char *emsg, va_list ap)
|
||||
{
|
||||
static char s[BUFSIZ];
|
||||
const char *sep;
|
||||
|
||||
if (emsg != NULL) {
|
||||
(void)vsnprintf(s, sizeof(s), emsg, ap);
|
||||
sep = ": ";
|
||||
} else {
|
||||
s[0] = '\0';
|
||||
sep = "";
|
||||
}
|
||||
if (code)
|
||||
logit(LOG_CRIT, "%s: %s%s%s",
|
||||
log_procname, s, sep, strerror(code));
|
||||
else
|
||||
logit(LOG_CRIT, "%s%s%s", log_procname, sep, s);
|
||||
}
|
||||
|
||||
void
|
||||
fatal(const char *emsg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, emsg);
|
||||
vfatalc(errno, emsg, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
fatalx(const char *emsg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, emsg);
|
||||
vfatalc(0, emsg, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
625
agent/main.c
Normal file
625
agent/main.c
Normal file
|
@ -0,0 +1,625 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "xml.h"
|
||||
|
||||
__dead void usage(void);
|
||||
static struct system_config *agent_init(void);
|
||||
static void agent_free(struct system_config *);
|
||||
static int agent_pf(struct system_config *, int);
|
||||
static void agent_unconfigure(void);
|
||||
|
||||
int
|
||||
shell(const char *arg, ...)
|
||||
{
|
||||
const char **argv, *a;
|
||||
int argc, i = 0, status;
|
||||
va_list ap;
|
||||
pid_t pid, child_pid;
|
||||
struct sigaction sigint, sigquit;
|
||||
sigset_t mask, omask;
|
||||
|
||||
/* create arguments */
|
||||
va_start(ap, arg);
|
||||
for (argc = 2; va_arg(ap, const char *) != NULL; argc++)
|
||||
;
|
||||
va_end(ap);
|
||||
|
||||
if ((argv = calloc(argc, sizeof(const char *))) == NULL)
|
||||
fatal("%s: calloc", __func__);
|
||||
argv[i++] = arg;
|
||||
|
||||
va_start(ap, arg);
|
||||
while ((a = va_arg(ap, char *)) != NULL)
|
||||
argv[i++] = a;
|
||||
va_end(ap);
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &mask, &omask);
|
||||
|
||||
/* run command in forked process */
|
||||
switch (child_pid = fork()) {
|
||||
case -1:
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
free(argv);
|
||||
return (-1);
|
||||
case 0:
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
execvp(argv[0], (char *const *)(caddr_t)argv);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
sigaction(SIGINT, NULL, &sigint);
|
||||
sigaction(SIGQUIT, NULL, &sigquit);
|
||||
|
||||
do {
|
||||
pid = waitpid(child_pid, &status, 0);
|
||||
} while (pid == -1 && errno == EINTR);
|
||||
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
sigaction(SIGINT, &sigint, NULL);
|
||||
sigaction(SIGQUIT, &sigquit, NULL);
|
||||
|
||||
/* Simplified return value: returns 0 on success and -1 on error */
|
||||
if (pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||
return (0);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
shellout(const char *in, char **out, const char *arg, ...)
|
||||
{
|
||||
const char **argv = NULL, *a;
|
||||
int argc, i = 0, status;
|
||||
va_list ap;
|
||||
pid_t pid, child_pid;
|
||||
struct sigaction sigint, sigquit;
|
||||
sigset_t mask, omask;
|
||||
FILE *outfp = NULL, *fp = NULL;
|
||||
char *outbuf;
|
||||
size_t outbufsz;
|
||||
char buf[BUFSIZ];
|
||||
int fdi[2], fdo[2];
|
||||
|
||||
if (out)
|
||||
*out = NULL;
|
||||
|
||||
/* create arguments */
|
||||
va_start(ap, arg);
|
||||
for (argc = 2; va_arg(ap, const char *) != NULL; argc++)
|
||||
;
|
||||
va_end(ap);
|
||||
|
||||
if ((argv = calloc(argc, sizeof(const char *))) == NULL)
|
||||
fatal("%s: calloc", __func__);
|
||||
argv[i++] = arg;
|
||||
|
||||
va_start(ap, arg);
|
||||
while ((a = va_arg(ap, char *)) != NULL)
|
||||
argv[i++] = a;
|
||||
va_end(ap);
|
||||
|
||||
if (in && socketpair(AF_UNIX,
|
||||
SOCK_STREAM|SOCK_CLOEXEC, AF_UNSPEC, fdi) == -1)
|
||||
goto fail;
|
||||
|
||||
if (out && socketpair(AF_UNIX,
|
||||
SOCK_STREAM|SOCK_CLOEXEC, AF_UNSPEC, fdo) == -1)
|
||||
goto fail;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &mask, &omask);
|
||||
|
||||
/* run command in forked process */
|
||||
switch (child_pid = fork()) {
|
||||
case -1:
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
goto fail;
|
||||
case 0:
|
||||
if (in) {
|
||||
close(fdi[1]);
|
||||
if (dup2(fdi[0], STDIN_FILENO) == -1)
|
||||
_exit(127);
|
||||
}
|
||||
if (out) {
|
||||
close(fdo[1]);
|
||||
if (dup2(fdo[0], STDOUT_FILENO) == -1)
|
||||
_exit(127);
|
||||
}
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
execvp(argv[0], (char *const *)(caddr_t)argv);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
sigaction(SIGINT, NULL, &sigint);
|
||||
sigaction(SIGQUIT, NULL, &sigquit);
|
||||
|
||||
if (in) {
|
||||
close(fdi[0]);
|
||||
if ((fp = fdopen(fdi[1], "w")) != NULL) {
|
||||
fputs(in, fp);
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
close(fdi[1]);
|
||||
}
|
||||
|
||||
if (out) {
|
||||
close(fdo[0]);
|
||||
if ((fp = fdopen(fdo[1], "r")) != NULL &&
|
||||
(outfp = open_memstream(&outbuf, &outbufsz)) != NULL) {
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
fputs(buf, outfp);
|
||||
}
|
||||
fclose(outfp);
|
||||
*out = outbuf;
|
||||
}
|
||||
fclose(fp);
|
||||
close(fdo[1]);
|
||||
}
|
||||
|
||||
do {
|
||||
pid = waitpid(child_pid, &status, 0);
|
||||
} while (pid == -1 && errno == EINTR);
|
||||
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
sigaction(SIGINT, &sigint, NULL);
|
||||
sigaction(SIGQUIT, &sigquit, NULL);
|
||||
|
||||
/* Simplified return value: returns 0 on success and -1 on error */
|
||||
if (pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
free(argv);
|
||||
if (out) {
|
||||
free(*out);
|
||||
*out = NULL;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
disable_output(struct system_config *sc, int fd)
|
||||
{
|
||||
int oldfd;
|
||||
|
||||
if (log_getverbose() > 2)
|
||||
return (-1);
|
||||
|
||||
if ((oldfd = dup(fd)) == -1 ||
|
||||
dup2(sc->sc_nullfd, fd) == -1)
|
||||
return (-1);
|
||||
|
||||
return (oldfd);
|
||||
}
|
||||
|
||||
int
|
||||
enable_output(struct system_config *sc, int fd, int oldfd)
|
||||
{
|
||||
if (oldfd == -1)
|
||||
return (0);
|
||||
|
||||
close(fd);
|
||||
if (dup2(oldfd, fd) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct system_config *
|
||||
agent_init(void)
|
||||
{
|
||||
struct system_config *sc;
|
||||
|
||||
if ((sc = calloc(1, sizeof(*sc))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
TAILQ_INIT(&sc->sc_pubkeys);
|
||||
|
||||
if ((sc->sc_nullfd = open("/dev/null", O_RDWR)) == -1) {
|
||||
free(sc);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (sc);
|
||||
}
|
||||
|
||||
static void
|
||||
agent_free(struct system_config *sc)
|
||||
{
|
||||
struct ssh_pubkey *ssh;
|
||||
|
||||
free(sc->sc_hostname);
|
||||
free(sc->sc_username);
|
||||
free(sc->sc_password);
|
||||
free(sc->sc_userdata);
|
||||
free(sc->sc_endpoint);
|
||||
free(sc->sc_instance);
|
||||
close(sc->sc_nullfd);
|
||||
|
||||
while ((ssh = TAILQ_FIRST(&sc->sc_pubkeys))) {
|
||||
free(ssh->ssh_keyval);
|
||||
free(ssh->ssh_keyfp);
|
||||
TAILQ_REMOVE(&sc->sc_pubkeys, ssh, ssh_entry);
|
||||
free(ssh);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
agent_addpubkey(struct system_config *sc, const char *sshval, const char *sshfp)
|
||||
{
|
||||
struct ssh_pubkey *ssh;
|
||||
|
||||
/* Ignore if neither key nor fingerprint is available */
|
||||
if (sshval == NULL && sshfp == NULL)
|
||||
return (0);
|
||||
|
||||
if ((ssh = calloc(1, sizeof(*ssh))) == NULL)
|
||||
return (-1);
|
||||
|
||||
if (sshfp != NULL && (ssh->ssh_keyfp = strdup(sshfp)) == NULL) {
|
||||
free(ssh);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (sshval != NULL && (ssh->ssh_keyval = strdup(sshval)) == NULL) {
|
||||
free(ssh->ssh_keyfp);
|
||||
free(ssh);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&sc->sc_pubkeys, ssh, ssh_entry);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
agent_setpubkey(struct system_config *sc, const char *sshval, const char *sshfp)
|
||||
{
|
||||
struct ssh_pubkey *ssh;
|
||||
int ret = 0;
|
||||
char *v = NULL;
|
||||
|
||||
TAILQ_FOREACH(ssh, &sc->sc_pubkeys, ssh_entry) {
|
||||
if (sshfp && ssh->ssh_keyfp &&
|
||||
strcasecmp(ssh->ssh_keyfp, sshfp) == 0) {
|
||||
if ((sshval == NULL) ||
|
||||
(sshval && (v = strdup(sshval)) == NULL))
|
||||
break;
|
||||
v[strcspn(v, "\r\n")] = '\0';
|
||||
free(ssh->ssh_keyval);
|
||||
ssh->ssh_keyval = v;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
fileout(const char *str, const char *mode, const char *fmt, ...)
|
||||
{
|
||||
FILE *fp;
|
||||
va_list ap;
|
||||
char *path;
|
||||
int ret;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vasprintf(&path, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ret == -1)
|
||||
return (-1);
|
||||
if ((fp = fopen(path, mode)) == NULL) {
|
||||
free(path);
|
||||
return (-1);
|
||||
}
|
||||
if (str != NULL) {
|
||||
fputs(str, fp);
|
||||
if (strpbrk(str, "\r\n") == NULL)
|
||||
fputs("\n", fp);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
free(path);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char *
|
||||
filein(const char *mode, const char *fmt, ...)
|
||||
{
|
||||
FILE *fp;
|
||||
va_list ap;
|
||||
char *path;
|
||||
int ret;
|
||||
char buf[BUFSIZ];
|
||||
FILE *infp;
|
||||
char *inbuf;
|
||||
size_t inbufsz;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vasprintf(&path, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ret == -1)
|
||||
return (NULL);
|
||||
if ((fp = fopen(path, mode)) == NULL) {
|
||||
free(path);
|
||||
return (NULL);
|
||||
}
|
||||
free(path);
|
||||
if ((infp = open_memstream(&inbuf, &inbufsz)) == NULL)
|
||||
fclose(fp);
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
fputs(buf, infp);
|
||||
}
|
||||
fclose(fp);
|
||||
fclose(infp);
|
||||
|
||||
return (inbuf);
|
||||
}
|
||||
|
||||
static int
|
||||
agent_pf(struct system_config *sc, int open)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (shell("rcctl", "get", "pf", "status", NULL) != 0)
|
||||
return (0);
|
||||
|
||||
if (open)
|
||||
ret = shellout("pass out proto tcp from egress to port www\n",
|
||||
NULL, "pfctl", "-f", "-", NULL);
|
||||
else
|
||||
ret = shellout("\n", NULL, "pfctl", "-f", "-", NULL);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
agent_configure(struct system_config *sc, int noaction)
|
||||
{
|
||||
struct ssh_pubkey *ssh;
|
||||
char *str1, *str2;
|
||||
|
||||
/* Skip configuration on the same instance */
|
||||
if ((str1 = filein("r", "/var/db/cloud-instance")) != NULL &&
|
||||
strcmp(sc->sc_instance, str1) == 0) {
|
||||
free(str1);
|
||||
return (0);
|
||||
}
|
||||
free(str1);
|
||||
|
||||
if (!noaction &&
|
||||
fileout(sc->sc_instance, "w", "/var/db/cloud-instance") != 0)
|
||||
log_warnx("instance failed");
|
||||
|
||||
/* hostname */
|
||||
log_debug("%s: hostname %s", __func__, sc->sc_hostname);
|
||||
if (!noaction &&
|
||||
fileout(sc->sc_hostname, "w", "/etc/myname") != 0)
|
||||
log_warnx("hostname failed");
|
||||
else
|
||||
(void)shell("hostname", sc->sc_hostname, NULL);
|
||||
|
||||
/* username */
|
||||
log_debug("%s: username %s", __func__, sc->sc_username);
|
||||
if (!noaction &&
|
||||
shell("useradd", "-L", "staff", "-G", "wheel",
|
||||
"-m", sc->sc_username, NULL) != 0)
|
||||
log_warnx("username failed");
|
||||
|
||||
/* password */
|
||||
if (sc->sc_password == NULL) {
|
||||
str1 = "/PasswordAuthentication/"
|
||||
"s/.*/PasswordAuthentication no/";
|
||||
str2 = "permit keepenv nopass :wheel as root\n"
|
||||
"permit keepenv nopass root\n";
|
||||
} else {
|
||||
if (!noaction &&
|
||||
shell("usermod", "-p", sc->sc_password,
|
||||
sc->sc_username, NULL) != 0)
|
||||
log_warnx("password failed");
|
||||
|
||||
str1 = "/PasswordAuthentication/"
|
||||
"s/.*/PasswordAuthentication yes/";
|
||||
str2 = "permit keepenv persist :wheel as root\n"
|
||||
"permit keepenv nopass root\n";
|
||||
}
|
||||
|
||||
/* doas */
|
||||
if (fileout(str2, "w", "/etc/doas.conf") != 0)
|
||||
log_warnx("doas failed");
|
||||
|
||||
/* ssh configuration */
|
||||
if (sc->sc_password == NULL && !TAILQ_EMPTY(&sc->sc_pubkeys))
|
||||
str1 = "/PasswordAuthentication/"
|
||||
"s/.*/PasswordAuthentication no/";
|
||||
else
|
||||
str1 = "/PasswordAuthentication/"
|
||||
"s/.*/PasswordAuthentication yes/";
|
||||
shell("sed", "-i", "-e", str1,
|
||||
"-e", "/ClientAliveInterval/s/.*/ClientAliveInterval 180/",
|
||||
"/etc/ssh/sshd_config",
|
||||
NULL);
|
||||
|
||||
/* ssh public keys */
|
||||
TAILQ_FOREACH(ssh, &sc->sc_pubkeys, ssh_entry) {
|
||||
if (ssh->ssh_keyval == NULL)
|
||||
continue;
|
||||
log_debug("%s: key %s", __func__, ssh->ssh_keyval);
|
||||
if (!noaction &&
|
||||
fileout(ssh->ssh_keyval, "a",
|
||||
"/home/%s/.ssh/authorized_keys",
|
||||
sc->sc_username) != 0)
|
||||
log_warnx("public key failed");
|
||||
}
|
||||
|
||||
if (sc->sc_userdata) {
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
log_debug("%s: %s", __func__, "/etc/rc.firsttime");
|
||||
if (!noaction && fileout("logger -s -t cloud-agent <<EOF\n"
|
||||
"#############################################################\n"
|
||||
"-----BEGIN SSH HOST KEY FINGERPRINTS-----\n"
|
||||
"$(for _f in /etc/ssh/ssh_host_*_key.pub;"
|
||||
" do ssh-keygen -lf ${_f}; done)\n"
|
||||
"-----END SSH HOST KEY FINGERPRINTS-----\n"
|
||||
"#############################################################\n"
|
||||
"EOF\n",
|
||||
"a", "/etc/rc.firsttime") != 0)
|
||||
log_warnx("userdata failed");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
agent_unconfigure(void)
|
||||
{
|
||||
/* Disable root pasword */
|
||||
(void)shell("chpass", "-a",
|
||||
"root:*:0:0:daemon:0:0:Charlie &:/root:/bin/ksh", NULL);
|
||||
|
||||
/* Delete keys */
|
||||
(void)shell("sh", "-c",
|
||||
"rm -rf /etc/{iked,isakmpd}/{local.pub,private/local.key}"
|
||||
" /etc/ssh/ssh_host_*"
|
||||
" /etc/dhclient.conf /var/db/dhclient.leases.*"
|
||||
" /tmp/{.[!.],}*", NULL);
|
||||
|
||||
/* Delete old seed files */
|
||||
(void)fileout(NULL, "w", "/etc/random.seed");
|
||||
(void)fileout(NULL, "w", "/var/db/host.random");
|
||||
|
||||
/* Clear logfiles */
|
||||
(void)shell("sh", "-c",
|
||||
"for _l in $(find /var/log -type f ! -name '*.gz' -size +0); do"
|
||||
" >${_l}; "
|
||||
"done", NULL);
|
||||
|
||||
(void)fileout("permit keepenv persist :wheel as root\n"
|
||||
"permit keepenv nopass root\n", "w", "/etc/doas.conf");
|
||||
}
|
||||
|
||||
__dead void
|
||||
usage(void)
|
||||
{
|
||||
extern char *__progname;
|
||||
|
||||
fprintf(stderr, "usage: %s [-nuv] interface\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *const *argv)
|
||||
{
|
||||
struct system_config *sc;
|
||||
int verbose = 0, noaction = 0, unconfigure = 0;
|
||||
int ch, ret;
|
||||
|
||||
while ((ch = getopt(argc, argv, "nvu")) != -1) {
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
noaction = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose += 2;
|
||||
break;
|
||||
case 'u':
|
||||
unconfigure = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
/* log to stderr */
|
||||
log_init(1, LOG_DAEMON);
|
||||
log_setverbose(verbose);
|
||||
|
||||
if (unconfigure) {
|
||||
agent_unconfigure();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
if (pledge("stdio cpath rpath wpath exec proc dns inet", NULL) == -1)
|
||||
fatal("pledge");
|
||||
|
||||
if ((sc = agent_init()) == NULL)
|
||||
fatalx("agent");
|
||||
|
||||
sc->sc_interface = argv[0];
|
||||
|
||||
if (agent_pf(sc, 1) != 0)
|
||||
fatalx("pf");
|
||||
|
||||
if (http_init() == -1)
|
||||
fatalx("http_init");
|
||||
|
||||
/*
|
||||
* XXX Detect cloud with help from hostctl and sysctl
|
||||
* XXX in addition to the interface name.
|
||||
*/
|
||||
if (strcmp("hvn0", sc->sc_interface) == 0)
|
||||
ret = azure(sc);
|
||||
else if (strcmp("xnf0", sc->sc_interface) == 0)
|
||||
ret = ec2(sc);
|
||||
else if (strcmp("vio0", sc->sc_interface) == 0)
|
||||
ret = cloudinit(sc);
|
||||
else
|
||||
fatal("unsupported cloud interface %s", sc->sc_interface);
|
||||
|
||||
if (agent_pf(sc, 0) != 0)
|
||||
fatalx("pf");
|
||||
|
||||
if (pledge("stdio cpath rpath wpath exec proc", NULL) == -1)
|
||||
fatal("pledge");
|
||||
|
||||
if (ret == 0 && agent_configure(sc, noaction) != 0)
|
||||
fatal("provisioning failed");
|
||||
|
||||
agent_free(sc);
|
||||
|
||||
return (0);
|
||||
}
|
94
agent/main.h
Normal file
94
agent/main.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "http.h"
|
||||
|
||||
struct ssh_pubkey {
|
||||
char *ssh_keyval;
|
||||
char *ssh_keyfp;
|
||||
|
||||
TAILQ_ENTRY(ssh_pubkey) ssh_entry;
|
||||
};
|
||||
TAILQ_HEAD(ssh_pubkeys, ssh_pubkey);
|
||||
|
||||
struct system_config {
|
||||
char *sc_hostname;
|
||||
char *sc_username;
|
||||
char *sc_password;
|
||||
char *sc_pubkey;
|
||||
unsigned char *sc_userdata;
|
||||
size_t sc_userdatalen;
|
||||
char *sc_endpoint;
|
||||
char *sc_instance;
|
||||
|
||||
const char *sc_ovfenv;
|
||||
const char *sc_interface;
|
||||
const char *sc_cdrom;
|
||||
|
||||
struct source sc_addr;
|
||||
struct ssh_pubkeys sc_pubkeys;
|
||||
|
||||
int sc_nullfd;
|
||||
void *sc_priv;
|
||||
};
|
||||
|
||||
/* azure.c */
|
||||
int azure(struct system_config *);
|
||||
|
||||
/* cloudinit.c */
|
||||
int ec2(struct system_config *);
|
||||
int cloudinit(struct system_config *);
|
||||
|
||||
/* main.c */
|
||||
int shell(const char *, ...);
|
||||
int shellout(const char *, char **, const char *, ...);
|
||||
int disable_output(struct system_config *, int);
|
||||
int enable_output(struct system_config *, int, int);
|
||||
int agent_addpubkey(struct system_config *, const char *, const char *);
|
||||
int agent_setpubkey(struct system_config *, const char *, const char *);
|
||||
int agent_configure(struct system_config *, int);
|
||||
|
||||
/* log.c */
|
||||
void log_init(int, int);
|
||||
void log_procinit(const char *);
|
||||
void log_setverbose(int);
|
||||
int log_getverbose(void);
|
||||
void log_warn(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void log_warnx(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void log_info(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void log_debug(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
void logit(int, const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)));
|
||||
void vlog(int, const char *, va_list)
|
||||
__attribute__((__format__ (printf, 2, 0)));
|
||||
__dead void fatal(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
__dead void fatalx(const char *, ...)
|
||||
__attribute__((__format__ (printf, 1, 2)));
|
||||
|
||||
#endif /* MAIN_H */
|
363
agent/xml.c
Normal file
363
agent/xml.c
Normal file
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
|
||||
#include <expat.h>
|
||||
#include "main.h"
|
||||
#include "xml.h"
|
||||
|
||||
static void xml_start_element(void *, const char *, const char **);
|
||||
static void xml_end_element(void *, const char *);
|
||||
static void xml_char_data(void *, const char *, int);
|
||||
static void xml_inc(struct xmlelem *, int);
|
||||
|
||||
static void
|
||||
xml_inc(struct xmlelem *b, int depth)
|
||||
{
|
||||
struct xmlelem *xe;
|
||||
b->xe_depth += depth;
|
||||
TAILQ_FOREACH(xe, &b->xe_head, xe_entry)
|
||||
xml_inc(xe, depth);
|
||||
}
|
||||
|
||||
void
|
||||
xml_add(struct xmlelem *a, struct xmlelem *b)
|
||||
{
|
||||
xml_inc(b, a->xe_depth);
|
||||
TAILQ_INSERT_TAIL(&a->xe_head, b, xe_entry);
|
||||
}
|
||||
|
||||
void
|
||||
xml_delete(struct xmlhead *xh)
|
||||
{
|
||||
struct xmlelem *xe, *tmp;
|
||||
int i;
|
||||
|
||||
TAILQ_FOREACH_SAFE(xe, xh, xe_entry, tmp) {
|
||||
xml_delete(&xe->xe_head);
|
||||
TAILQ_REMOVE(xh, xe, xe_entry);
|
||||
|
||||
if (xe->xe_attr != NULL) {
|
||||
for (i = 0; xe->xe_attr[i] != NULL; i++)
|
||||
free(xe->xe_attr[i]);
|
||||
free(xe->xe_attr);
|
||||
}
|
||||
|
||||
free(xe->xe_data);
|
||||
free(xe->xe_tag);
|
||||
free(xe);
|
||||
}
|
||||
}
|
||||
|
||||
struct xmlelem *
|
||||
xml_get(struct xmlhead *root, const char *arg)
|
||||
{
|
||||
struct xmlelem *xe;
|
||||
|
||||
TAILQ_FOREACH(xe, root, xe_entry) {
|
||||
/* search case-insensitive */
|
||||
if (strcasecmp(xe->xe_tag, arg) == 0)
|
||||
return (xe);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct xmlelem *
|
||||
xml_findv(struct xmlhead *root, const char **argv, int argc)
|
||||
{
|
||||
struct xmlelem *xe = NULL;
|
||||
struct xmlhead *head = root;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if ((xe = xml_get(head, argv[i])) == NULL)
|
||||
break;
|
||||
head = &xe->xe_head;
|
||||
}
|
||||
|
||||
return (xe);
|
||||
}
|
||||
|
||||
struct xmlelem *
|
||||
xml_findl(struct xmlhead *root, const char *arg, ...)
|
||||
{
|
||||
struct xmlelem *xe = NULL;
|
||||
const char **argv = NULL;
|
||||
int argc, i;
|
||||
const char *tag;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, arg);
|
||||
for (argc = 1; va_arg(ap, const char *) != NULL; argc++)
|
||||
;
|
||||
va_end(ap);
|
||||
|
||||
if ((argv = calloc(argc, sizeof(const char *))) == NULL)
|
||||
fatal("calloc");
|
||||
i = 0;
|
||||
argv[i++] = arg;
|
||||
|
||||
va_start(ap, arg);
|
||||
while ((tag = va_arg(ap, const char *)) != NULL)
|
||||
argv[i++] = tag;
|
||||
va_end(ap);
|
||||
|
||||
xe = xml_findv(root, argv, argc);
|
||||
free(argv);
|
||||
|
||||
return (xe);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print XML tree suitable for OVF
|
||||
*
|
||||
* This parser and printer does not support CDATA with embedded
|
||||
* elements which is not required for OVF - it is more or less a simple
|
||||
* key/value store without HTML-like markup.
|
||||
*/
|
||||
void
|
||||
xml_print(struct xml *env, struct xmlelem *xe, int data_only, FILE *fp)
|
||||
{
|
||||
struct xmlelem *xelm;
|
||||
int i;
|
||||
|
||||
if (xe == NULL)
|
||||
return;
|
||||
|
||||
if (data_only) {
|
||||
if (xe->xe_datalen)
|
||||
fprintf(fp, "%*s\n",
|
||||
(int)xe->xe_datalen, xe->xe_data);
|
||||
TAILQ_FOREACH(xelm, &xe->xe_head, xe_entry)
|
||||
xml_print(env, xelm, data_only, fp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print XML header for the root node */
|
||||
if (xe->xe_parent == NULL)
|
||||
fprintf(fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||
|
||||
fprintf(fp, "%*s<%s", xe->xe_depth * 2, "", xe->xe_tag);
|
||||
for (i = 0; xe->xe_attr[i] != NULL; i += 2) {
|
||||
fprintf(fp, " %s=\"%s\"",
|
||||
xe->xe_attr[i], xe->xe_attr[i + 1]);
|
||||
}
|
||||
fprintf(fp, ">");
|
||||
|
||||
if (xe->xe_datalen)
|
||||
fprintf(fp, "%*s",
|
||||
(int)xe->xe_datalen, xe->xe_data);
|
||||
|
||||
if (!TAILQ_EMPTY(&xe->xe_head))
|
||||
fprintf(fp, "\n");
|
||||
|
||||
TAILQ_FOREACH(xelm, &xe->xe_head, xe_entry)
|
||||
xml_print(env, xelm, data_only, fp);
|
||||
|
||||
if (TAILQ_EMPTY(&xe->xe_head))
|
||||
fprintf(fp, "</%s>\n", xe->xe_tag);
|
||||
else
|
||||
fprintf(fp, "%*s</%s>\n", xe->xe_depth * 2, "", xe->xe_tag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple XML parser
|
||||
*/
|
||||
|
||||
static void
|
||||
xml_start_element(void *data, const char *el, const char **attr)
|
||||
{
|
||||
struct xml *env = data;
|
||||
struct xmlelem *xe;
|
||||
struct xmlhead *xh;
|
||||
int i;
|
||||
|
||||
if ((xe = calloc(1, sizeof(*xe))) == NULL)
|
||||
fatal("callac");
|
||||
TAILQ_INIT(&xe->xe_head);
|
||||
|
||||
if (env->ox_cur == NULL)
|
||||
xh = &env->ox_root;
|
||||
else
|
||||
xh = &env->ox_cur->xe_head;
|
||||
|
||||
xe->xe_parent = env->ox_cur;
|
||||
xe->xe_depth = env->ox_depth;
|
||||
if ((xe->xe_tag = strdup(el)) == NULL)
|
||||
fatal("strdup");
|
||||
|
||||
TAILQ_INSERT_TAIL(xh, xe, xe_entry);
|
||||
env->ox_cur = xe;
|
||||
|
||||
/* Copy attributes */
|
||||
for (i = 0; attr[i] != NULL; i += 2)
|
||||
;
|
||||
xe->xe_nattr = i / 2;
|
||||
|
||||
if ((xe->xe_attr = calloc(i + 1, sizeof(char *))) == NULL)
|
||||
fatal("calloc");
|
||||
|
||||
for (i = 0; attr[i] != NULL; i++) {
|
||||
if ((xe->xe_attr[i] = strdup(attr[i])) == NULL)
|
||||
fatal("strdup");
|
||||
}
|
||||
|
||||
env->ox_depth++;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_end_element(void *data, const char *el)
|
||||
{
|
||||
struct xml *env = data;
|
||||
struct xmlelem *xe = env->ox_cur;
|
||||
|
||||
if (xe == NULL || strcmp(xe->xe_tag, el) != 0)
|
||||
fatal("unexpected closing tag: %s <> %s", el, xe->xe_tag);
|
||||
if (xe->xe_data == NULL)
|
||||
xe->xe_data = strdup("");
|
||||
|
||||
env->ox_cur = xe->xe_parent;
|
||||
env->ox_depth--;
|
||||
}
|
||||
|
||||
static void
|
||||
xml_char_data(void *data, const char *s, int len)
|
||||
{
|
||||
struct xml *env = data;
|
||||
struct xmlelem *xe = env->ox_cur;
|
||||
char *p;
|
||||
int i;
|
||||
int ok = 0;
|
||||
off_t off = 0;
|
||||
|
||||
for (i = 0; i < len && s[i] != '\0'; i++) {
|
||||
if (!isspace(s[i])) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
/* XXX there might be a better way to handle libexpat cdata */
|
||||
if ((p = realloc(xe->xe_data, xe->xe_datalen + len + 2)) == NULL)
|
||||
fatal("realloc");
|
||||
if (xe->xe_datalen) {
|
||||
p[xe->xe_datalen] = '\n';
|
||||
off = 1;
|
||||
}
|
||||
memcpy(p + xe->xe_datalen + off, s, len);
|
||||
p[xe->xe_datalen + off + len] = '\0';
|
||||
|
||||
xe->xe_data = p;
|
||||
xe->xe_datalen += len + off;
|
||||
|
||||
env->ox_data = 1;
|
||||
}
|
||||
|
||||
int
|
||||
xml_init(struct xml *env)
|
||||
{
|
||||
XML_Parser parser;
|
||||
|
||||
memset(env, 0, sizeof(*env));
|
||||
TAILQ_INIT(&env->ox_root);
|
||||
|
||||
if ((parser = XML_ParserCreate(NULL)) == NULL)
|
||||
return (-1);
|
||||
env->ox_parser = parser;
|
||||
|
||||
XML_SetUserData(parser, env);
|
||||
XML_SetElementHandler(parser,
|
||||
xml_start_element, xml_end_element);
|
||||
XML_SetCharacterDataHandler(parser, xml_char_data);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
xml_free(struct xml *env)
|
||||
{
|
||||
if (env == NULL)
|
||||
return;
|
||||
if (env->ox_parser != NULL)
|
||||
XML_ParserFree(env->ox_parser);
|
||||
xml_delete(&env->ox_root);
|
||||
memset(env, 0, sizeof(*env));
|
||||
}
|
||||
|
||||
int
|
||||
xml_parse_buffer(struct xml *env, char *xml, size_t xmllen)
|
||||
{
|
||||
XML_Parser parser = env->ox_parser;
|
||||
|
||||
if (XML_Parse(parser, xml, xmllen,
|
||||
XML_TRUE) == XML_STATUS_ERROR)
|
||||
return (-1);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
env->ox_parser = NULL;
|
||||
|
||||
if (TAILQ_EMPTY(&env->ox_root))
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
xml_parse(struct xml *env, const char *file)
|
||||
{
|
||||
XML_Parser parser = env->ox_parser;
|
||||
int fd;
|
||||
void *xml;
|
||||
ssize_t len;
|
||||
|
||||
if ((fd = open(file, O_RDONLY)) == -1)
|
||||
fatal("open %s", file);
|
||||
|
||||
do {
|
||||
if ((xml = XML_GetBuffer(parser, BUFSIZ)) == NULL)
|
||||
fatalx("XML_GetBuffer");
|
||||
|
||||
if ((len = read(fd, xml, BUFSIZ)) <= 0)
|
||||
break;
|
||||
|
||||
if (XML_ParseBuffer(parser, len, XML_FALSE) == XML_STATUS_ERROR)
|
||||
fatalx("XML_ParseBuffer");
|
||||
} while (len == BUFSIZ);
|
||||
|
||||
close(fd);
|
||||
|
||||
if (XML_Parse(parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
|
||||
fatalx("XML_Parse");
|
||||
|
||||
XML_ParserFree(parser);
|
||||
env->ox_parser = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
58
agent/xml.h
Normal file
58
agent/xml.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OVFXML_H
|
||||
#define OVFXML_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
TAILQ_HEAD(xmlhead, xmlelem);
|
||||
|
||||
struct xmlelem {
|
||||
char *xe_tag;
|
||||
char **xe_attr;
|
||||
unsigned int xe_nattr;
|
||||
unsigned int xe_depth;
|
||||
char *xe_data;
|
||||
size_t xe_datalen;
|
||||
struct xmlelem *xe_parent;
|
||||
struct xmlhead xe_head;
|
||||
TAILQ_ENTRY(xmlelem) xe_entry;
|
||||
};
|
||||
|
||||
struct xml {
|
||||
int ox_depth;
|
||||
int ox_data;
|
||||
struct xmlhead ox_root;
|
||||
struct xmlelem *ox_cur;
|
||||
struct xmlelem *ox_prev;
|
||||
void *ox_parser;
|
||||
};
|
||||
|
||||
int xml_init(struct xml *);
|
||||
void xml_free(struct xml *);
|
||||
void xml_add(struct xmlelem *, struct xmlelem *);
|
||||
void xml_delete(struct xmlhead *);
|
||||
struct xmlelem *xml_get(struct xmlhead *, const char *);
|
||||
struct xmlelem *xml_findv(struct xmlhead *, const char **, int);
|
||||
struct xmlelem *xml_findl(struct xmlhead *, const char *, ...);
|
||||
void xml_print(struct xml *, struct xmlelem *, int, FILE *);
|
||||
int xml_parse_buffer(struct xml *, char *, size_t);
|
||||
int xml_parse(struct xml *, const char *);
|
||||
|
||||
#endif /* OVFXML_H */
|
3
cms/Makefile
Normal file
3
cms/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
SUBDIR= lib bin
|
||||
|
||||
.include <bsd.subdir.mk>
|
20
cms/Makefile.inc
Normal file
20
cms/Makefile.inc
Normal file
|
@ -0,0 +1,20 @@
|
|||
.include <bsd.own.mk>
|
||||
.include <bsd.obj.mk>
|
||||
|
||||
BINDIR?= /usr/local/bin
|
||||
|
||||
LIBCRYPTOSRC= ${BSDSRCDIR}/lib/libcrypto
|
||||
|
||||
CFLAGS+= -I${.CURDIR}
|
||||
CFLAGS+= -I${.CURDIR}/../lib
|
||||
CFLAGS+= -I${LIBCRYPTOSRC}/asn1
|
||||
CFLAGS+= -I${LIBCRYPTOSRC}/evp
|
||||
CFLAGS+= -Wall
|
||||
|
||||
.if exists(${.CURDIR}/../lib/${__objdir})
|
||||
LDADD+= -L${.CURDIR}/../lib/${__objdir} -lcms
|
||||
DPADD+= ${.CURDIR}/../lib/${__objdir}/libcms.a
|
||||
.else
|
||||
LDADD+= -L${.CURDIR}/../lib -lcms
|
||||
DPADD+= ${.CURDIR}/../lib/libcms.a
|
||||
.endif
|
9
cms/bin/Makefile
Normal file
9
cms/bin/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
.PATH: ${BSDSRCDIR}/usr.bin/openssl
|
||||
|
||||
PROG= cms
|
||||
SRCS= cms.c apps.c app_rand.c
|
||||
|
||||
LDADD+= -lcrypto
|
||||
NOMAN= yes
|
||||
|
||||
.include <bsd.prog.mk>
|
203
cms/bin/app_rand.c
Normal file
203
cms/bin/app_rand.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
/* apps/app_rand.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#define NON_MAIN
|
||||
#include "apps.h"
|
||||
#undef NON_MAIN
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
static int seeded = 0;
|
||||
|
||||
int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn)
|
||||
{
|
||||
int consider_randfile = (file == NULL);
|
||||
char buffer[200];
|
||||
|
||||
#ifdef OPENSSL_SYS_WINDOWS
|
||||
RAND_screen();
|
||||
#endif
|
||||
|
||||
if (file == NULL)
|
||||
file = RAND_file_name(buffer, sizeof buffer);
|
||||
if (file == NULL || !RAND_load_file(file, -1)) {
|
||||
if (RAND_status() == 0) {
|
||||
if (!dont_warn) {
|
||||
BIO_printf(bio_e, "unable to load 'random state'\n");
|
||||
BIO_printf(bio_e,
|
||||
"This means that the random number generator has not been seeded\n");
|
||||
BIO_printf(bio_e, "with much random data.\n");
|
||||
if (consider_randfile) { /* explanation does not apply when a
|
||||
* file is explicitly named */
|
||||
BIO_printf(bio_e,
|
||||
"Consider setting the RANDFILE environment variable to point at a file that\n");
|
||||
BIO_printf(bio_e,
|
||||
"'random' data can be kept in (the file will be overwritten).\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
seeded = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long app_RAND_load_files(char *name)
|
||||
{
|
||||
char *p, *n;
|
||||
int last;
|
||||
long tot = 0;
|
||||
|
||||
for (;;) {
|
||||
last = 0;
|
||||
for (p = name; ((*p != '\0') && (*p != ':')); p++) ;
|
||||
if (*p == '\0')
|
||||
last = 1;
|
||||
*p = '\0';
|
||||
n = name;
|
||||
name = p + 1;
|
||||
if (*n == '\0')
|
||||
break;
|
||||
|
||||
tot += RAND_load_file(n, -1);
|
||||
if (last)
|
||||
break;
|
||||
}
|
||||
if (tot > 512)
|
||||
app_RAND_allow_write_file();
|
||||
return (tot);
|
||||
}
|
||||
|
||||
int app_RAND_write_file(const char *file, BIO *bio_e)
|
||||
{
|
||||
char buffer[200];
|
||||
|
||||
if (!seeded)
|
||||
/*
|
||||
* If we did not manage to read the seed file, we should not write a
|
||||
* low-entropy seed file back -- it would suppress a crucial warning
|
||||
* the next time we want to use it.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
if (file == NULL)
|
||||
file = RAND_file_name(buffer, sizeof buffer);
|
||||
if (file == NULL || !RAND_write_file(file)) {
|
||||
BIO_printf(bio_e, "unable to write 'random state'\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void app_RAND_allow_write_file(void)
|
||||
{
|
||||
seeded = 1;
|
||||
}
|
3251
cms/bin/apps.c
Normal file
3251
cms/bin/apps.c
Normal file
File diff suppressed because it is too large
Load diff
385
cms/bin/apps.h
Normal file
385
cms/bin/apps.h
Normal file
|
@ -0,0 +1,385 @@
|
|||
/* apps/apps.h */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HEADER_APPS_H
|
||||
# define HEADER_APPS_H
|
||||
|
||||
# include <openssl/bio.h>
|
||||
# include <openssl/x509.h>
|
||||
# include <openssl/lhash.h>
|
||||
# include <openssl/conf.h>
|
||||
# include <openssl/txt_db.h>
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
# include <openssl/engine.h>
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
# include <openssl/ocsp.h>
|
||||
# endif
|
||||
# include <openssl/ossl_typ.h>
|
||||
|
||||
#include "libressl_apps.h"
|
||||
|
||||
int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn);
|
||||
int app_RAND_write_file(const char *file, BIO *bio_e);
|
||||
/*
|
||||
* When `file' is NULL, use defaults. `bio_e' is for error messages.
|
||||
*/
|
||||
void app_RAND_allow_write_file(void);
|
||||
long app_RAND_load_files(char *file); /* `file' is a list of files to read,
|
||||
* separated by LIST_SEPARATOR_CHAR
|
||||
* (see e_os.h). The string is
|
||||
* destroyed! */
|
||||
|
||||
# ifndef MONOLITH
|
||||
|
||||
# define MAIN(a,v) main(a,v)
|
||||
|
||||
# ifndef NON_MAIN
|
||||
CONF *config = NULL;
|
||||
BIO *bio_err = NULL;
|
||||
# else
|
||||
extern CONF *config;
|
||||
extern BIO *bio_err;
|
||||
# endif
|
||||
|
||||
# else
|
||||
|
||||
# define MAIN(a,v) PROG(a,v)
|
||||
extern CONF *config;
|
||||
extern char *default_config_file;
|
||||
extern BIO *bio_err;
|
||||
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_SYS_NETWARE
|
||||
# include <signal.h>
|
||||
# endif
|
||||
|
||||
# ifdef SIGPIPE
|
||||
# define do_pipe_sig() signal(SIGPIPE,SIG_IGN)
|
||||
# else
|
||||
# define do_pipe_sig()
|
||||
# endif
|
||||
|
||||
# ifdef OPENSSL_NO_COMP
|
||||
# define zlib_cleanup()
|
||||
# else
|
||||
# define zlib_cleanup() COMP_zlib_cleanup()
|
||||
# endif
|
||||
|
||||
# if defined(MONOLITH) && !defined(OPENSSL_C)
|
||||
# define apps_startup() \
|
||||
do_pipe_sig()
|
||||
# define apps_shutdown()
|
||||
# else
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
# define apps_startup() \
|
||||
do { do_pipe_sig(); CRYPTO_malloc_init(); \
|
||||
ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); \
|
||||
ENGINE_load_builtin_engines(); setup_ui_method(); } while(0)
|
||||
# define apps_shutdown() \
|
||||
do { CONF_modules_unload(1); destroy_ui_method(); \
|
||||
OBJ_cleanup(); EVP_cleanup(); ENGINE_cleanup(); \
|
||||
CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); \
|
||||
RAND_cleanup(); \
|
||||
ERR_free_strings(); zlib_cleanup();} while(0)
|
||||
# else
|
||||
# define apps_startup() \
|
||||
do { do_pipe_sig(); CRYPTO_malloc_init(); \
|
||||
ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); \
|
||||
setup_ui_method(); } while(0)
|
||||
# define apps_shutdown() \
|
||||
do { CONF_modules_unload(1); destroy_ui_method(); \
|
||||
OBJ_cleanup(); EVP_cleanup(); \
|
||||
CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); \
|
||||
RAND_cleanup(); \
|
||||
ERR_free_strings(); zlib_cleanup(); } while(0)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(OPENSSL_SYSNAME_WIN32) || defined(OPENSSL_SYSNAME_WINCE)
|
||||
# define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
|
||||
# else
|
||||
# define openssl_fdset(a,b) FD_SET(a, b)
|
||||
# endif
|
||||
|
||||
typedef struct args_st {
|
||||
char **data;
|
||||
int count;
|
||||
} ARGS;
|
||||
|
||||
# define PW_MIN_LENGTH 4
|
||||
typedef struct pw_cb_data {
|
||||
const void *password;
|
||||
const char *prompt_info;
|
||||
} PW_CB_DATA;
|
||||
|
||||
int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data);
|
||||
|
||||
int setup_ui_method(void);
|
||||
void destroy_ui_method(void);
|
||||
|
||||
int should_retry(int i);
|
||||
int args_from_file(char *file, int *argc, char **argv[]);
|
||||
int str2fmt(char *s);
|
||||
void program_name(char *in, char *out, int size);
|
||||
int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]);
|
||||
# ifdef HEADER_X509_H
|
||||
int dump_cert_text(BIO *out, X509 *x);
|
||||
void print_name(BIO *out, const char *title, X509_NAME *nm,
|
||||
unsigned long lflags);
|
||||
# endif
|
||||
int set_cert_ex(unsigned long *flags, const char *arg);
|
||||
int set_name_ex(unsigned long *flags, const char *arg);
|
||||
int set_ext_copy(int *copy_type, const char *arg);
|
||||
int copy_extensions(X509 *x, X509_REQ *req, int copy_type);
|
||||
int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2);
|
||||
int add_oid_section(BIO *err, CONF *conf);
|
||||
X509 *load_cert(BIO *err, const char *file, int format,
|
||||
const char *pass, ENGINE *e, const char *cert_descrip);
|
||||
X509_CRL *load_crl(const char *infile, int format);
|
||||
int load_cert_crl_http(const char *url, BIO *err,
|
||||
X509 **pcert, X509_CRL **pcrl);
|
||||
EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
|
||||
const char *pass, ENGINE *e, const char *key_descrip);
|
||||
EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
|
||||
const char *pass, ENGINE *e, const char *key_descrip);
|
||||
STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
|
||||
const char *pass, ENGINE *e,
|
||||
const char *cert_descrip);
|
||||
STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format,
|
||||
const char *pass, ENGINE *e,
|
||||
const char *cert_descrip);
|
||||
X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath);
|
||||
# ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE *setup_engine(BIO *err, const char *engine, int debug);
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_OCSP
|
||||
OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
|
||||
const char *host, const char *path,
|
||||
const char *port, int use_ssl,
|
||||
const STACK_OF(CONF_VALUE) *headers,
|
||||
int req_timeout);
|
||||
# endif
|
||||
|
||||
int load_config(BIO *err, CONF *cnf);
|
||||
char *make_config_name(void);
|
||||
|
||||
/* Functions defined in ca.c and also used in ocsp.c */
|
||||
int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
|
||||
ASN1_GENERALIZEDTIME **pinvtm, const char *str);
|
||||
|
||||
# define DB_type 0
|
||||
# define DB_exp_date 1
|
||||
# define DB_rev_date 2
|
||||
# define DB_serial 3 /* index - unique */
|
||||
# define DB_file 4
|
||||
# define DB_name 5 /* index - unique when active and not
|
||||
* disabled */
|
||||
# define DB_NUMBER 6
|
||||
|
||||
# define DB_TYPE_REV 'R'
|
||||
# define DB_TYPE_EXP 'E'
|
||||
# define DB_TYPE_VAL 'V'
|
||||
|
||||
typedef struct db_attr_st {
|
||||
int unique_subject;
|
||||
} DB_ATTR;
|
||||
typedef struct ca_db_st {
|
||||
DB_ATTR attributes;
|
||||
TXT_DB *db;
|
||||
} CA_DB;
|
||||
|
||||
BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai);
|
||||
int save_serial(char *serialfile, char *suffix, BIGNUM *serial,
|
||||
ASN1_INTEGER **retai);
|
||||
int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix);
|
||||
int rand_serial(BIGNUM *b, ASN1_INTEGER *ai);
|
||||
CA_DB *load_index(char *dbfile, DB_ATTR *dbattr);
|
||||
int index_index(CA_DB *db);
|
||||
int save_index(const char *dbfile, const char *suffix, CA_DB *db);
|
||||
int rotate_index(const char *dbfile, const char *new_suffix,
|
||||
const char *old_suffix);
|
||||
void free_index(CA_DB *db);
|
||||
# define index_name_cmp_noconst(a, b) \
|
||||
index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
|
||||
(const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
|
||||
int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
|
||||
int parse_yesno(const char *str, int def);
|
||||
|
||||
X509_NAME *parse_name(char *str, long chtype, int multirdn);
|
||||
int args_verify(char ***pargs, int *pargc,
|
||||
int *badarg, BIO *err, X509_VERIFY_PARAM **pm);
|
||||
void policies_print(BIO *out, X509_STORE_CTX *ctx);
|
||||
int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
|
||||
int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value);
|
||||
int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx,
|
||||
const char *algname, ENGINE *e, int do_param);
|
||||
int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
|
||||
STACK_OF(OPENSSL_STRING) *sigopts);
|
||||
int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
|
||||
STACK_OF(OPENSSL_STRING) *sigopts);
|
||||
int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
|
||||
STACK_OF(OPENSSL_STRING) *sigopts);
|
||||
# ifndef OPENSSL_NO_PSK
|
||||
extern char *psk_key;
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_JPAKE
|
||||
void jpake_client_auth(BIO *out, BIO *conn, const char *secret);
|
||||
void jpake_server_auth(BIO *out, BIO *conn, const char *secret);
|
||||
# endif
|
||||
|
||||
# ifndef OPENSSL_NO_TLSEXT
|
||||
unsigned char *next_protos_parse(unsigned short *outlen, const char *in);
|
||||
# endif /* ndef OPENSSL_NO_TLSEXT */
|
||||
|
||||
void store_setup_crl_download(X509_STORE *st);
|
||||
|
||||
# define FORMAT_UNDEF 0
|
||||
# define FORMAT_ASN1 1
|
||||
# define FORMAT_TEXT 2
|
||||
# define FORMAT_PEM 3
|
||||
# define FORMAT_NETSCAPE 4
|
||||
# define FORMAT_PKCS12 5
|
||||
# define FORMAT_SMIME 6
|
||||
# define FORMAT_ENGINE 7
|
||||
# define FORMAT_IISSGC 8 /* XXX this stupid macro helps us to avoid
|
||||
* adding yet another param to load_*key() */
|
||||
# define FORMAT_PEMRSA 9 /* PEM RSAPubicKey format */
|
||||
# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */
|
||||
# define FORMAT_MSBLOB 11 /* MS Key blob format */
|
||||
# define FORMAT_PVK 12 /* MS PVK file format */
|
||||
# define FORMAT_HTTP 13 /* Download using HTTP */
|
||||
|
||||
# define EXT_COPY_NONE 0
|
||||
# define EXT_COPY_ADD 1
|
||||
# define EXT_COPY_ALL 2
|
||||
|
||||
# define NETSCAPE_CERT_HDR "certificate"
|
||||
|
||||
# define APP_PASS_LEN 1024
|
||||
|
||||
# define SERIAL_RAND_BITS 64
|
||||
|
||||
int app_isdir(const char *);
|
||||
int fileno_stdin(void);
|
||||
int fileno_stdout(void);
|
||||
int raw_read_stdin(void *, int);
|
||||
int raw_write_stdout(const void *, int);
|
||||
|
||||
# define TM_START 0
|
||||
# define TM_STOP 1
|
||||
double app_tminterval(int stop, int usertime);
|
||||
|
||||
# define OPENSSL_NO_SSL_INTERN
|
||||
|
||||
#endif
|
1354
cms/bin/cms.c
Normal file
1354
cms/bin/cms.c
Normal file
File diff suppressed because it is too large
Load diff
19
cms/bin/libressl_apps.h
Normal file
19
cms/bin/libressl_apps.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/asn1.h>
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/cms.h>
|
||||
#else
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
#endif
|
||||
#include "apps.h"
|
||||
#include <unistd.h>
|
||||
|
||||
#define OPENSSL_CONF "openssl.cnf"
|
||||
#define OPENSSL_NO_ENGINE
|
||||
#define MS_STATIC static
|
||||
int cms_main(int argc, char **argv);
|
19
cms/lib/Makefile
Normal file
19
cms/lib/Makefile
Normal file
|
@ -0,0 +1,19 @@
|
|||
LIB= cms
|
||||
|
||||
SRCS+= cms_asn1.c cms_dd.c cms_err.c cms_kari.c cms_sd.c
|
||||
SRCS+= cms_att.c cms_enc.c cms_ess.c cms_lib.c cms_smime.c
|
||||
SRCS+= cms_cd.c cms_env.c cms_io.c cms_pwri.c
|
||||
SRCS+= libressl_pkey.c libressl_stubs.c
|
||||
|
||||
DEBUGLIBS= no
|
||||
NOPROFILE= yes
|
||||
NOPIC= yes
|
||||
|
||||
LDADD+= -lcrypto
|
||||
NOMAN= yes
|
||||
|
||||
install:
|
||||
@echo -n
|
||||
|
||||
.include <bsd.own.mk>
|
||||
.include <bsd.lib.mk>
|
155
cms/lib/asn1_locl.h
Normal file
155
cms/lib/asn1_locl.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/* $OpenBSD: asn1_locl.h,v 1.8 2016/12/21 15:49:29 jsing Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
__BEGIN_HIDDEN_DECLS
|
||||
|
||||
/* Internal ASN1 structures and functions: not for application use */
|
||||
|
||||
/* ASN1 print context structure */
|
||||
|
||||
struct asn1_pctx_st {
|
||||
unsigned long flags;
|
||||
unsigned long nm_flags;
|
||||
unsigned long cert_flags;
|
||||
unsigned long oid_flags;
|
||||
unsigned long str_flags;
|
||||
} /* ASN1_PCTX */;
|
||||
|
||||
/* ASN1 public key method structure */
|
||||
|
||||
struct evp_pkey_asn1_method_st {
|
||||
int pkey_id;
|
||||
int pkey_base_id;
|
||||
unsigned long pkey_flags;
|
||||
|
||||
char *pem_str;
|
||||
char *info;
|
||||
|
||||
int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub);
|
||||
int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk);
|
||||
int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
|
||||
int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx);
|
||||
|
||||
int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf);
|
||||
int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk);
|
||||
int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx);
|
||||
|
||||
int (*pkey_size)(const EVP_PKEY *pk);
|
||||
int (*pkey_bits)(const EVP_PKEY *pk);
|
||||
|
||||
int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder,
|
||||
int derlen);
|
||||
int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder);
|
||||
int (*param_missing)(const EVP_PKEY *pk);
|
||||
int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
|
||||
int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
|
||||
int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx);
|
||||
int (*sig_print)(BIO *out, const X509_ALGOR *sigalg,
|
||||
const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx);
|
||||
|
||||
void (*pkey_free)(EVP_PKEY *pkey);
|
||||
int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
|
||||
|
||||
/* Legacy functions for old PEM */
|
||||
|
||||
int (*old_priv_decode)(EVP_PKEY *pkey, const unsigned char **pder,
|
||||
int derlen);
|
||||
int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);
|
||||
/* Custom ASN1 signature verification */
|
||||
int (*item_verify)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
|
||||
X509_ALGOR *a, ASN1_BIT_STRING *sig, EVP_PKEY *pkey);
|
||||
int (*item_sign)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
|
||||
X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *sig);
|
||||
|
||||
} /* EVP_PKEY_ASN1_METHOD */;
|
||||
|
||||
/* Method to handle CRL access.
|
||||
* In general a CRL could be very large (several Mb) and can consume large
|
||||
* amounts of resources if stored in memory by multiple processes.
|
||||
* This method allows general CRL operations to be redirected to more
|
||||
* efficient callbacks: for example a CRL entry database.
|
||||
*/
|
||||
|
||||
#define X509_CRL_METHOD_DYNAMIC 1
|
||||
|
||||
struct x509_crl_method_st {
|
||||
int flags;
|
||||
int (*crl_init)(X509_CRL *crl);
|
||||
int (*crl_free)(X509_CRL *crl);
|
||||
int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
|
||||
ASN1_INTEGER *ser, X509_NAME *issuer);
|
||||
int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
|
||||
};
|
||||
|
||||
/*
|
||||
* Unicode codepoint constants
|
||||
*/
|
||||
#define UNICODE_MAX 0x10FFFF
|
||||
#define UNICODE_SURROGATE_MIN 0x00D800
|
||||
#define UNICODE_SURROGATE_MAX 0x00DFFF
|
||||
|
||||
#define UNICODE_IS_SURROGATE(x) \
|
||||
((x) >= UNICODE_SURROGATE_MIN && (x) <= UNICODE_SURROGATE_MAX)
|
||||
|
||||
int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
|
||||
int UTF8_putc(unsigned char *str, int len, unsigned long value);
|
||||
|
||||
__END_HIDDEN_DECLS
|
579
cms/lib/asn1_mac.h
Normal file
579
cms/lib/asn1_mac.h
Normal file
|
@ -0,0 +1,579 @@
|
|||
/* crypto/asn1/asn1_mac.h */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef HEADER_ASN1_MAC_H
|
||||
# define HEADER_ASN1_MAC_H
|
||||
|
||||
# include <openssl/asn1.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
# ifndef ASN1_MAC_ERR_LIB
|
||||
# define ASN1_MAC_ERR_LIB ERR_LIB_ASN1
|
||||
# endif
|
||||
|
||||
# define ASN1_MAC_H_err(f,r,line) \
|
||||
ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line))
|
||||
|
||||
# define M_ASN1_D2I_vars(a,type,func) \
|
||||
ASN1_const_CTX c; \
|
||||
type ret=NULL; \
|
||||
\
|
||||
c.pp=(const unsigned char **)pp; \
|
||||
c.q= *(const unsigned char **)pp; \
|
||||
c.error=ERR_R_NESTED_ASN1_ERROR; \
|
||||
if ((a == NULL) || ((*a) == NULL)) \
|
||||
{ if ((ret=(type)func()) == NULL) \
|
||||
{ c.line=__LINE__; goto err; } } \
|
||||
else ret=(*a);
|
||||
|
||||
# define M_ASN1_D2I_Init() \
|
||||
c.p= *(const unsigned char **)pp; \
|
||||
c.max=(length == 0)?0:(c.p+length);
|
||||
|
||||
# define M_ASN1_D2I_Finish_2(a) \
|
||||
if (!asn1_const_Finish(&c)) \
|
||||
{ c.line=__LINE__; goto err; } \
|
||||
*(const unsigned char **)pp=c.p; \
|
||||
if (a != NULL) (*a)=ret; \
|
||||
return(ret);
|
||||
|
||||
# define M_ASN1_D2I_Finish(a,func,e) \
|
||||
M_ASN1_D2I_Finish_2(a); \
|
||||
err:\
|
||||
ASN1_MAC_H_err((e),c.error,c.line); \
|
||||
asn1_add_error(*(const unsigned char **)pp,(int)(c.q- *pp)); \
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
|
||||
return(NULL)
|
||||
|
||||
# define M_ASN1_D2I_start_sequence() \
|
||||
if (!asn1_GetSequence(&c,&length)) \
|
||||
{ c.line=__LINE__; goto err; }
|
||||
/* Begin reading ASN1 without a surrounding sequence */
|
||||
# define M_ASN1_D2I_begin() \
|
||||
c.slen = length;
|
||||
|
||||
/* End reading ASN1 with no check on length */
|
||||
# define M_ASN1_D2I_Finish_nolen(a, func, e) \
|
||||
*pp=c.p; \
|
||||
if (a != NULL) (*a)=ret; \
|
||||
return(ret); \
|
||||
err:\
|
||||
ASN1_MAC_H_err((e),c.error,c.line); \
|
||||
asn1_add_error(*pp,(int)(c.q- *pp)); \
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
|
||||
return(NULL)
|
||||
|
||||
# define M_ASN1_D2I_end_sequence() \
|
||||
(((c.inf&1) == 0)?(c.slen <= 0): \
|
||||
(c.eos=ASN1_const_check_infinite_end(&c.p,c.slen)))
|
||||
|
||||
/* Don't use this with d2i_ASN1_BOOLEAN() */
|
||||
# define M_ASN1_D2I_get(b, func) \
|
||||
c.q=c.p; \
|
||||
if (func(&(b),&c.p,c.slen) == NULL) \
|
||||
{c.line=__LINE__; goto err; } \
|
||||
c.slen-=(c.p-c.q);
|
||||
|
||||
/* Don't use this with d2i_ASN1_BOOLEAN() */
|
||||
# define M_ASN1_D2I_get_x(type,b,func) \
|
||||
c.q=c.p; \
|
||||
if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \
|
||||
{c.line=__LINE__; goto err; } \
|
||||
c.slen-=(c.p-c.q);
|
||||
|
||||
/* use this instead () */
|
||||
# define M_ASN1_D2I_get_int(b,func) \
|
||||
c.q=c.p; \
|
||||
if (func(&(b),&c.p,c.slen) < 0) \
|
||||
{c.line=__LINE__; goto err; } \
|
||||
c.slen-=(c.p-c.q);
|
||||
|
||||
# define M_ASN1_D2I_get_opt(b,func,type) \
|
||||
if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
|
||||
== (V_ASN1_UNIVERSAL|(type)))) \
|
||||
{ \
|
||||
M_ASN1_D2I_get(b,func); \
|
||||
}
|
||||
|
||||
# define M_ASN1_D2I_get_int_opt(b,func,type) \
|
||||
if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
|
||||
== (V_ASN1_UNIVERSAL|(type)))) \
|
||||
{ \
|
||||
M_ASN1_D2I_get_int(b,func); \
|
||||
}
|
||||
|
||||
# define M_ASN1_D2I_get_imp(b,func, type) \
|
||||
M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
|
||||
c.q=c.p; \
|
||||
if (func(&(b),&c.p,c.slen) == NULL) \
|
||||
{c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
|
||||
c.slen-=(c.p-c.q);\
|
||||
M_ASN1_next_prev=_tmp;
|
||||
|
||||
# define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \
|
||||
if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \
|
||||
(V_ASN1_CONTEXT_SPECIFIC|(tag)))) \
|
||||
{ \
|
||||
unsigned char _tmp = M_ASN1_next; \
|
||||
M_ASN1_D2I_get_imp(b,func, type);\
|
||||
}
|
||||
|
||||
# define M_ASN1_D2I_get_set(r,func,free_func) \
|
||||
M_ASN1_D2I_get_imp_set(r,func,free_func, \
|
||||
V_ASN1_SET,V_ASN1_UNIVERSAL);
|
||||
|
||||
# define M_ASN1_D2I_get_set_type(type,r,func,free_func) \
|
||||
M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \
|
||||
V_ASN1_SET,V_ASN1_UNIVERSAL);
|
||||
|
||||
# define M_ASN1_D2I_get_set_opt(r,func,free_func) \
|
||||
if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
|
||||
V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
|
||||
{ M_ASN1_D2I_get_set(r,func,free_func); }
|
||||
|
||||
# define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \
|
||||
if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
|
||||
V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
|
||||
{ M_ASN1_D2I_get_set_type(type,r,func,free_func); }
|
||||
|
||||
# define M_ASN1_I2D_len_SET_opt(a,f) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
M_ASN1_I2D_len_SET(a,f);
|
||||
|
||||
# define M_ASN1_I2D_put_SET_opt(a,f) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
M_ASN1_I2D_put_SET(a,f);
|
||||
|
||||
# define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
M_ASN1_I2D_put_SEQUENCE(a,f);
|
||||
|
||||
# define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0)) \
|
||||
M_ASN1_I2D_put_SEQUENCE_type(type,a,f);
|
||||
|
||||
# define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
|
||||
if ((c.slen != 0) && \
|
||||
(M_ASN1_next == \
|
||||
(V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
|
||||
{ \
|
||||
M_ASN1_D2I_get_imp_set(b,func,free_func,\
|
||||
tag,V_ASN1_CONTEXT_SPECIFIC); \
|
||||
}
|
||||
|
||||
# define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \
|
||||
if ((c.slen != 0) && \
|
||||
(M_ASN1_next == \
|
||||
(V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
|
||||
{ \
|
||||
M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\
|
||||
tag,V_ASN1_CONTEXT_SPECIFIC); \
|
||||
}
|
||||
|
||||
# define M_ASN1_D2I_get_seq(r,func,free_func) \
|
||||
M_ASN1_D2I_get_imp_set(r,func,free_func,\
|
||||
V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
|
||||
|
||||
# define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \
|
||||
M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
|
||||
V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
|
||||
|
||||
# define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
|
||||
if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
|
||||
V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
|
||||
{ M_ASN1_D2I_get_seq(r,func,free_func); }
|
||||
|
||||
# define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \
|
||||
if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
|
||||
V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
|
||||
{ M_ASN1_D2I_get_seq_type(type,r,func,free_func); }
|
||||
|
||||
# define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
|
||||
M_ASN1_D2I_get_imp_set(r,func,free_func,\
|
||||
x,V_ASN1_CONTEXT_SPECIFIC);
|
||||
|
||||
# define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \
|
||||
M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
|
||||
x,V_ASN1_CONTEXT_SPECIFIC);
|
||||
|
||||
# define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
|
||||
c.q=c.p; \
|
||||
if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
|
||||
(void (*)())free_func,a,b) == NULL) \
|
||||
{ c.line=__LINE__; goto err; } \
|
||||
c.slen-=(c.p-c.q);
|
||||
|
||||
# define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
|
||||
c.q=c.p; \
|
||||
if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
|
||||
free_func,a,b) == NULL) \
|
||||
{ c.line=__LINE__; goto err; } \
|
||||
c.slen-=(c.p-c.q);
|
||||
|
||||
# define M_ASN1_D2I_get_set_strings(r,func,a,b) \
|
||||
c.q=c.p; \
|
||||
if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
|
||||
{ c.line=__LINE__; goto err; } \
|
||||
c.slen-=(c.p-c.q);
|
||||
|
||||
# define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
|
||||
if ((c.slen != 0L) && (M_ASN1_next == \
|
||||
(V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
|
||||
{ \
|
||||
int Tinf,Ttag,Tclass; \
|
||||
long Tlen; \
|
||||
\
|
||||
c.q=c.p; \
|
||||
Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
|
||||
if (Tinf & 0x80) \
|
||||
{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
|
||||
c.line=__LINE__; goto err; } \
|
||||
if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
|
||||
Tlen = c.slen - (c.p - c.q) - 2; \
|
||||
if (func(&(r),&c.p,Tlen) == NULL) \
|
||||
{ c.line=__LINE__; goto err; } \
|
||||
if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
|
||||
Tlen = c.slen - (c.p - c.q); \
|
||||
if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \
|
||||
{ c.error=ERR_R_MISSING_ASN1_EOS; \
|
||||
c.line=__LINE__; goto err; } \
|
||||
}\
|
||||
c.slen-=(c.p-c.q); \
|
||||
}
|
||||
|
||||
# define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
|
||||
if ((c.slen != 0) && (M_ASN1_next == \
|
||||
(V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
|
||||
{ \
|
||||
int Tinf,Ttag,Tclass; \
|
||||
long Tlen; \
|
||||
\
|
||||
c.q=c.p; \
|
||||
Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
|
||||
if (Tinf & 0x80) \
|
||||
{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
|
||||
c.line=__LINE__; goto err; } \
|
||||
if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
|
||||
Tlen = c.slen - (c.p - c.q) - 2; \
|
||||
if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
|
||||
(void (*)())free_func, \
|
||||
b,V_ASN1_UNIVERSAL) == NULL) \
|
||||
{ c.line=__LINE__; goto err; } \
|
||||
if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
|
||||
Tlen = c.slen - (c.p - c.q); \
|
||||
if(!ASN1_check_infinite_end(&c.p, Tlen)) \
|
||||
{ c.error=ERR_R_MISSING_ASN1_EOS; \
|
||||
c.line=__LINE__; goto err; } \
|
||||
}\
|
||||
c.slen-=(c.p-c.q); \
|
||||
}
|
||||
|
||||
# define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \
|
||||
if ((c.slen != 0) && (M_ASN1_next == \
|
||||
(V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
|
||||
{ \
|
||||
int Tinf,Ttag,Tclass; \
|
||||
long Tlen; \
|
||||
\
|
||||
c.q=c.p; \
|
||||
Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
|
||||
if (Tinf & 0x80) \
|
||||
{ c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
|
||||
c.line=__LINE__; goto err; } \
|
||||
if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
|
||||
Tlen = c.slen - (c.p - c.q) - 2; \
|
||||
if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
|
||||
free_func,b,V_ASN1_UNIVERSAL) == NULL) \
|
||||
{ c.line=__LINE__; goto err; } \
|
||||
if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
|
||||
Tlen = c.slen - (c.p - c.q); \
|
||||
if(!ASN1_check_infinite_end(&c.p, Tlen)) \
|
||||
{ c.error=ERR_R_MISSING_ASN1_EOS; \
|
||||
c.line=__LINE__; goto err; } \
|
||||
}\
|
||||
c.slen-=(c.p-c.q); \
|
||||
}
|
||||
|
||||
/* New macros */
|
||||
# define M_ASN1_New_Malloc(ret,type) \
|
||||
if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \
|
||||
{ c.line=__LINE__; goto err2; }
|
||||
|
||||
# define M_ASN1_New(arg,func) \
|
||||
if (((arg)=func()) == NULL) return(NULL)
|
||||
|
||||
# define M_ASN1_New_Error(a) \
|
||||
/*- err: ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \
|
||||
return(NULL);*/ \
|
||||
err2: ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \
|
||||
return(NULL)
|
||||
|
||||
/*
|
||||
* BIG UGLY WARNING! This is so damn ugly I wanna puke. Unfortunately, some
|
||||
* macros that use ASN1_const_CTX still insist on writing in the input
|
||||
* stream. ARGH! ARGH! ARGH! Let's get rid of this macro package. Please? --
|
||||
* Richard Levitte
|
||||
*/
|
||||
# define M_ASN1_next (*((unsigned char *)(c.p)))
|
||||
# define M_ASN1_next_prev (*((unsigned char *)(c.q)))
|
||||
|
||||
/*************************************************/
|
||||
|
||||
# define M_ASN1_I2D_vars(a) int r=0,ret=0; \
|
||||
unsigned char *p; \
|
||||
if (a == NULL) return(0)
|
||||
|
||||
/* Length Macros */
|
||||
# define M_ASN1_I2D_len(a,f) ret+=f(a,NULL)
|
||||
# define M_ASN1_I2D_len_IMP_opt(a,f) if (a != NULL) M_ASN1_I2D_len(a,f)
|
||||
|
||||
# define M_ASN1_I2D_len_SET(a,f) \
|
||||
ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
|
||||
|
||||
# define M_ASN1_I2D_len_SET_type(type,a,f) \
|
||||
ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \
|
||||
V_ASN1_UNIVERSAL,IS_SET);
|
||||
|
||||
# define M_ASN1_I2D_len_SEQUENCE(a,f) \
|
||||
ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
|
||||
IS_SEQUENCE);
|
||||
|
||||
# define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \
|
||||
ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \
|
||||
V_ASN1_UNIVERSAL,IS_SEQUENCE)
|
||||
|
||||
# define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
M_ASN1_I2D_len_SEQUENCE(a,f);
|
||||
|
||||
# define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0)) \
|
||||
M_ASN1_I2D_len_SEQUENCE_type(type,a,f);
|
||||
|
||||
# define M_ASN1_I2D_len_IMP_SET(a,f,x) \
|
||||
ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);
|
||||
|
||||
# define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \
|
||||
ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
|
||||
V_ASN1_CONTEXT_SPECIFIC,IS_SET);
|
||||
|
||||
# define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SET);
|
||||
|
||||
# define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0)) \
|
||||
ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
|
||||
V_ASN1_CONTEXT_SPECIFIC,IS_SET);
|
||||
|
||||
# define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
|
||||
ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SEQUENCE);
|
||||
|
||||
# define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SEQUENCE);
|
||||
|
||||
# define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0)) \
|
||||
ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
|
||||
V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SEQUENCE);
|
||||
|
||||
# define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
|
||||
if (a != NULL)\
|
||||
{ \
|
||||
v=f(a,NULL); \
|
||||
ret+=ASN1_object_size(1,v,mtag); \
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
|
||||
if ((a != NULL) && (sk_num(a) != 0))\
|
||||
{ \
|
||||
v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
|
||||
ret+=ASN1_object_size(1,v,mtag); \
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
|
||||
if ((a != NULL) && (sk_num(a) != 0))\
|
||||
{ \
|
||||
v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
|
||||
IS_SEQUENCE); \
|
||||
ret+=ASN1_object_size(1,v,mtag); \
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0))\
|
||||
{ \
|
||||
v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \
|
||||
V_ASN1_UNIVERSAL, \
|
||||
IS_SEQUENCE); \
|
||||
ret+=ASN1_object_size(1,v,mtag); \
|
||||
}
|
||||
|
||||
/* Put Macros */
|
||||
# define M_ASN1_I2D_put(a,f) f(a,&p)
|
||||
|
||||
# define M_ASN1_I2D_put_IMP_opt(a,f,t) \
|
||||
if (a != NULL) \
|
||||
{ \
|
||||
unsigned char *q=p; \
|
||||
f(a,&p); \
|
||||
*q=(V_ASN1_CONTEXT_SPECIFIC|t|(*q&V_ASN1_CONSTRUCTED));\
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
|
||||
V_ASN1_UNIVERSAL,IS_SET)
|
||||
# define M_ASN1_I2D_put_SET_type(type,a,f) \
|
||||
i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET)
|
||||
# define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
|
||||
V_ASN1_CONTEXT_SPECIFIC,IS_SET)
|
||||
# define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \
|
||||
i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET)
|
||||
# define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
|
||||
V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)
|
||||
|
||||
# define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
|
||||
V_ASN1_UNIVERSAL,IS_SEQUENCE)
|
||||
|
||||
# define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \
|
||||
i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
|
||||
IS_SEQUENCE)
|
||||
|
||||
# define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
M_ASN1_I2D_put_SEQUENCE(a,f);
|
||||
|
||||
# define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
{ i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SET); }
|
||||
|
||||
# define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0)) \
|
||||
{ i2d_ASN1_SET_OF_##type(a,&p,f,x, \
|
||||
V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SET); }
|
||||
|
||||
# define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
{ i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SEQUENCE); }
|
||||
|
||||
# define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0)) \
|
||||
{ i2d_ASN1_SET_OF_##type(a,&p,f,x, \
|
||||
V_ASN1_CONTEXT_SPECIFIC, \
|
||||
IS_SEQUENCE); }
|
||||
|
||||
# define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
|
||||
if (a != NULL) \
|
||||
{ \
|
||||
ASN1_put_object(&p,1,v,tag,V_ASN1_CONTEXT_SPECIFIC); \
|
||||
f(a,&p); \
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
{ \
|
||||
ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
|
||||
i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
|
||||
if ((a != NULL) && (sk_num(a) != 0)) \
|
||||
{ \
|
||||
ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
|
||||
i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
|
||||
if ((a != NULL) && (sk_##type##_num(a) != 0)) \
|
||||
{ \
|
||||
ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
|
||||
i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \
|
||||
IS_SEQUENCE); \
|
||||
}
|
||||
|
||||
# define M_ASN1_I2D_seq_total() \
|
||||
r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); \
|
||||
if (pp == NULL) return(r); \
|
||||
p= *pp; \
|
||||
ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
|
||||
|
||||
# define M_ASN1_I2D_INF_seq_start(tag,ctx) \
|
||||
*(p++)=(V_ASN1_CONSTRUCTED|(tag)|(ctx)); \
|
||||
*(p++)=0x80
|
||||
|
||||
# define M_ASN1_I2D_INF_seq_end() *(p++)=0x00; *(p++)=0x00
|
||||
|
||||
# define M_ASN1_I2D_finish() *pp=p; \
|
||||
return(r);
|
||||
|
||||
int asn1_GetSequence(ASN1_const_CTX *c, long *length);
|
||||
void asn1_add_error(const unsigned char *address, int offset);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
973
cms/lib/asn1t.h
Normal file
973
cms/lib/asn1t.h
Normal file
|
@ -0,0 +1,973 @@
|
|||
/* asn1t.h */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2000.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
#ifndef HEADER_ASN1T_H
|
||||
# define HEADER_ASN1T_H
|
||||
|
||||
# include <stddef.h>
|
||||
# include <openssl/e_os2.h>
|
||||
# include <openssl/asn1.h>
|
||||
|
||||
# ifdef OPENSSL_BUILD_SHLIBCRYPTO
|
||||
# undef OPENSSL_EXTERN
|
||||
# define OPENSSL_EXTERN OPENSSL_EXPORT
|
||||
# endif
|
||||
|
||||
/* ASN1 template defines, structures and functions */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
|
||||
|
||||
/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
|
||||
# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr))
|
||||
|
||||
/* Macros for start and end of ASN1_ITEM definition */
|
||||
|
||||
# define ASN1_ITEM_start(itname) \
|
||||
OPENSSL_GLOBAL const ASN1_ITEM itname##_it = {
|
||||
|
||||
# define ASN1_ITEM_end(itname) \
|
||||
};
|
||||
|
||||
# else
|
||||
|
||||
/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
|
||||
# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr()))
|
||||
|
||||
/* Macros for start and end of ASN1_ITEM definition */
|
||||
|
||||
# define ASN1_ITEM_start(itname) \
|
||||
const ASN1_ITEM * itname##_it(void) \
|
||||
{ \
|
||||
static const ASN1_ITEM local_it = {
|
||||
|
||||
# define ASN1_ITEM_end(itname) \
|
||||
}; \
|
||||
return &local_it; \
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
/* Macros to aid ASN1 template writing */
|
||||
|
||||
# define ASN1_ITEM_TEMPLATE(tname) \
|
||||
static const ASN1_TEMPLATE tname##_item_tt
|
||||
|
||||
# define ASN1_ITEM_TEMPLATE_END(tname) \
|
||||
;\
|
||||
ASN1_ITEM_start(tname) \
|
||||
ASN1_ITYPE_PRIMITIVE,\
|
||||
-1,\
|
||||
&tname##_item_tt,\
|
||||
0,\
|
||||
NULL,\
|
||||
0,\
|
||||
#tname \
|
||||
ASN1_ITEM_end(tname)
|
||||
|
||||
/* This is a ASN1 type which just embeds a template */
|
||||
|
||||
/*-
|
||||
* This pair helps declare a SEQUENCE. We can do:
|
||||
*
|
||||
* ASN1_SEQUENCE(stname) = {
|
||||
* ... SEQUENCE components ...
|
||||
* } ASN1_SEQUENCE_END(stname)
|
||||
*
|
||||
* This will produce an ASN1_ITEM called stname_it
|
||||
* for a structure called stname.
|
||||
*
|
||||
* If you want the same structure but a different
|
||||
* name then use:
|
||||
*
|
||||
* ASN1_SEQUENCE(itname) = {
|
||||
* ... SEQUENCE components ...
|
||||
* } ASN1_SEQUENCE_END_name(stname, itname)
|
||||
*
|
||||
* This will create an item called itname_it using
|
||||
* a structure called stname.
|
||||
*/
|
||||
|
||||
# define ASN1_SEQUENCE(tname) \
|
||||
static const ASN1_TEMPLATE tname##_seq_tt[]
|
||||
|
||||
# define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname)
|
||||
|
||||
# define ASN1_SEQUENCE_END_name(stname, tname) \
|
||||
;\
|
||||
ASN1_ITEM_start(tname) \
|
||||
ASN1_ITYPE_SEQUENCE,\
|
||||
V_ASN1_SEQUENCE,\
|
||||
tname##_seq_tt,\
|
||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
|
||||
NULL,\
|
||||
sizeof(stname),\
|
||||
#stname \
|
||||
ASN1_ITEM_end(tname)
|
||||
|
||||
# define ASN1_NDEF_SEQUENCE(tname) \
|
||||
ASN1_SEQUENCE(tname)
|
||||
|
||||
# define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
|
||||
ASN1_SEQUENCE_cb(tname, cb)
|
||||
|
||||
# define ASN1_SEQUENCE_cb(tname, cb) \
|
||||
static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
|
||||
ASN1_SEQUENCE(tname)
|
||||
|
||||
# define ASN1_BROKEN_SEQUENCE(tname) \
|
||||
static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
|
||||
ASN1_SEQUENCE(tname)
|
||||
|
||||
# define ASN1_SEQUENCE_ref(tname, cb, lck) \
|
||||
static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \
|
||||
ASN1_SEQUENCE(tname)
|
||||
|
||||
# define ASN1_SEQUENCE_enc(tname, enc, cb) \
|
||||
static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \
|
||||
ASN1_SEQUENCE(tname)
|
||||
|
||||
# define ASN1_NDEF_SEQUENCE_END(tname) \
|
||||
;\
|
||||
ASN1_ITEM_start(tname) \
|
||||
ASN1_ITYPE_NDEF_SEQUENCE,\
|
||||
V_ASN1_SEQUENCE,\
|
||||
tname##_seq_tt,\
|
||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
|
||||
NULL,\
|
||||
sizeof(tname),\
|
||||
#tname \
|
||||
ASN1_ITEM_end(tname)
|
||||
|
||||
# define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
|
||||
|
||||
# define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
|
||||
|
||||
# define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
|
||||
|
||||
# define ASN1_SEQUENCE_END_ref(stname, tname) \
|
||||
;\
|
||||
ASN1_ITEM_start(tname) \
|
||||
ASN1_ITYPE_SEQUENCE,\
|
||||
V_ASN1_SEQUENCE,\
|
||||
tname##_seq_tt,\
|
||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
|
||||
&tname##_aux,\
|
||||
sizeof(stname),\
|
||||
#stname \
|
||||
ASN1_ITEM_end(tname)
|
||||
|
||||
# define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \
|
||||
;\
|
||||
ASN1_ITEM_start(tname) \
|
||||
ASN1_ITYPE_NDEF_SEQUENCE,\
|
||||
V_ASN1_SEQUENCE,\
|
||||
tname##_seq_tt,\
|
||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
|
||||
&tname##_aux,\
|
||||
sizeof(stname),\
|
||||
#stname \
|
||||
ASN1_ITEM_end(tname)
|
||||
|
||||
/*-
|
||||
* This pair helps declare a CHOICE type. We can do:
|
||||
*
|
||||
* ASN1_CHOICE(chname) = {
|
||||
* ... CHOICE options ...
|
||||
* ASN1_CHOICE_END(chname)
|
||||
*
|
||||
* This will produce an ASN1_ITEM called chname_it
|
||||
* for a structure called chname. The structure
|
||||
* definition must look like this:
|
||||
* typedef struct {
|
||||
* int type;
|
||||
* union {
|
||||
* ASN1_SOMETHING *opt1;
|
||||
* ASN1_SOMEOTHER *opt2;
|
||||
* } value;
|
||||
* } chname;
|
||||
*
|
||||
* the name of the selector must be 'type'.
|
||||
* to use an alternative selector name use the
|
||||
* ASN1_CHOICE_END_selector() version.
|
||||
*/
|
||||
|
||||
# define ASN1_CHOICE(tname) \
|
||||
static const ASN1_TEMPLATE tname##_ch_tt[]
|
||||
|
||||
# define ASN1_CHOICE_cb(tname, cb) \
|
||||
static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
|
||||
ASN1_CHOICE(tname)
|
||||
|
||||
# define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
|
||||
|
||||
# define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type)
|
||||
|
||||
# define ASN1_CHOICE_END_selector(stname, tname, selname) \
|
||||
;\
|
||||
ASN1_ITEM_start(tname) \
|
||||
ASN1_ITYPE_CHOICE,\
|
||||
offsetof(stname,selname) ,\
|
||||
tname##_ch_tt,\
|
||||
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
|
||||
NULL,\
|
||||
sizeof(stname),\
|
||||
#stname \
|
||||
ASN1_ITEM_end(tname)
|
||||
|
||||
# define ASN1_CHOICE_END_cb(stname, tname, selname) \
|
||||
;\
|
||||
ASN1_ITEM_start(tname) \
|
||||
ASN1_ITYPE_CHOICE,\
|
||||
offsetof(stname,selname) ,\
|
||||
tname##_ch_tt,\
|
||||
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
|
||||
&tname##_aux,\
|
||||
sizeof(stname),\
|
||||
#stname \
|
||||
ASN1_ITEM_end(tname)
|
||||
|
||||
/* This helps with the template wrapper form of ASN1_ITEM */
|
||||
|
||||
# define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
|
||||
(flags), (tag), 0,\
|
||||
#name, ASN1_ITEM_ref(type) }
|
||||
|
||||
/* These help with SEQUENCE or CHOICE components */
|
||||
|
||||
/* used to declare other types */
|
||||
|
||||
# define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
|
||||
(flags), (tag), offsetof(stname, field),\
|
||||
#field, ASN1_ITEM_ref(type) }
|
||||
|
||||
/* used when the structure is combined with the parent */
|
||||
|
||||
# define ASN1_EX_COMBINE(flags, tag, type) { \
|
||||
(flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) }
|
||||
|
||||
/* implicit and explicit helper macros */
|
||||
|
||||
# define ASN1_IMP_EX(stname, field, type, tag, ex) \
|
||||
ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type)
|
||||
|
||||
# define ASN1_EXP_EX(stname, field, type, tag, ex) \
|
||||
ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type)
|
||||
|
||||
/* Any defined by macros: the field used is in the table itself */
|
||||
|
||||
# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
|
||||
# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
|
||||
# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
|
||||
# else
|
||||
# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
|
||||
# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
|
||||
# endif
|
||||
/* Plain simple type */
|
||||
# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
|
||||
|
||||
/* OPTIONAL simple type */
|
||||
# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
|
||||
|
||||
/* IMPLICIT tagged simple type */
|
||||
# define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0)
|
||||
|
||||
/* IMPLICIT tagged OPTIONAL simple type */
|
||||
# define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
|
||||
|
||||
/* Same as above but EXPLICIT */
|
||||
|
||||
# define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0)
|
||||
# define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
|
||||
|
||||
/* SEQUENCE OF type */
|
||||
# define ASN1_SEQUENCE_OF(stname, field, type) \
|
||||
ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type)
|
||||
|
||||
/* OPTIONAL SEQUENCE OF */
|
||||
# define ASN1_SEQUENCE_OF_OPT(stname, field, type) \
|
||||
ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
|
||||
|
||||
/* Same as above but for SET OF */
|
||||
|
||||
# define ASN1_SET_OF(stname, field, type) \
|
||||
ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type)
|
||||
|
||||
# define ASN1_SET_OF_OPT(stname, field, type) \
|
||||
ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
|
||||
|
||||
/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */
|
||||
|
||||
# define ASN1_IMP_SET_OF(stname, field, type, tag) \
|
||||
ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
|
||||
|
||||
# define ASN1_EXP_SET_OF(stname, field, type, tag) \
|
||||
ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
|
||||
|
||||
# define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \
|
||||
ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
|
||||
|
||||
# define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \
|
||||
ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
|
||||
|
||||
# define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \
|
||||
ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
|
||||
|
||||
# define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \
|
||||
ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
|
||||
|
||||
# define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \
|
||||
ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
|
||||
|
||||
# define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
|
||||
ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
|
||||
|
||||
/* EXPLICIT using indefinite length constructed form */
|
||||
# define ASN1_NDEF_EXP(stname, field, type, tag) \
|
||||
ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
|
||||
|
||||
/* EXPLICIT OPTIONAL using indefinite length constructed form */
|
||||
# define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
|
||||
ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
|
||||
|
||||
/* Macros for the ASN1_ADB structure */
|
||||
|
||||
# define ASN1_ADB(name) \
|
||||
static const ASN1_ADB_TABLE name##_adbtbl[]
|
||||
|
||||
# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
|
||||
|
||||
# define ASN1_ADB_END(name, flags, field, app_table, def, none) \
|
||||
;\
|
||||
static const ASN1_ADB name##_adb = {\
|
||||
flags,\
|
||||
offsetof(name, field),\
|
||||
app_table,\
|
||||
name##_adbtbl,\
|
||||
sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
|
||||
def,\
|
||||
none\
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
# define ASN1_ADB_END(name, flags, field, app_table, def, none) \
|
||||
;\
|
||||
static const ASN1_ITEM *name##_adb(void) \
|
||||
{ \
|
||||
static const ASN1_ADB internal_adb = \
|
||||
{\
|
||||
flags,\
|
||||
offsetof(name, field),\
|
||||
app_table,\
|
||||
name##_adbtbl,\
|
||||
sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
|
||||
def,\
|
||||
none\
|
||||
}; \
|
||||
return (const ASN1_ITEM *) &internal_adb; \
|
||||
} \
|
||||
void dummy_function(void)
|
||||
|
||||
# endif
|
||||
|
||||
# define ADB_ENTRY(val, template) {val, template}
|
||||
|
||||
# define ASN1_ADB_TEMPLATE(name) \
|
||||
static const ASN1_TEMPLATE name##_tt
|
||||
|
||||
/*
|
||||
* This is the ASN1 template structure that defines a wrapper round the
|
||||
* actual type. It determines the actual position of the field in the value
|
||||
* structure, various flags such as OPTIONAL and the field name.
|
||||
*/
|
||||
|
||||
struct ASN1_TEMPLATE_st {
|
||||
unsigned long flags; /* Various flags */
|
||||
long tag; /* tag, not used if no tagging */
|
||||
unsigned long offset; /* Offset of this field in structure */
|
||||
# ifndef NO_ASN1_FIELD_NAMES
|
||||
const char *field_name; /* Field name */
|
||||
# endif
|
||||
ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */
|
||||
};
|
||||
|
||||
/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */
|
||||
|
||||
# define ASN1_TEMPLATE_item(t) (t->item_ptr)
|
||||
# define ASN1_TEMPLATE_adb(t) (t->item_ptr)
|
||||
|
||||
typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE;
|
||||
typedef struct ASN1_ADB_st ASN1_ADB;
|
||||
|
||||
struct ASN1_ADB_st {
|
||||
unsigned long flags; /* Various flags */
|
||||
unsigned long offset; /* Offset of selector field */
|
||||
STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */
|
||||
const ASN1_ADB_TABLE *tbl; /* Table of possible types */
|
||||
long tblcount; /* Number of entries in tbl */
|
||||
const ASN1_TEMPLATE *default_tt; /* Type to use if no match */
|
||||
const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */
|
||||
};
|
||||
|
||||
struct ASN1_ADB_TABLE_st {
|
||||
long value; /* NID for an object or value for an int */
|
||||
const ASN1_TEMPLATE tt; /* item for this value */
|
||||
};
|
||||
|
||||
/* template flags */
|
||||
|
||||
/* Field is optional */
|
||||
# define ASN1_TFLG_OPTIONAL (0x1)
|
||||
|
||||
/* Field is a SET OF */
|
||||
# define ASN1_TFLG_SET_OF (0x1 << 1)
|
||||
|
||||
/* Field is a SEQUENCE OF */
|
||||
# define ASN1_TFLG_SEQUENCE_OF (0x2 << 1)
|
||||
|
||||
/*
|
||||
* Special case: this refers to a SET OF that will be sorted into DER order
|
||||
* when encoded *and* the corresponding STACK will be modified to match the
|
||||
* new order.
|
||||
*/
|
||||
# define ASN1_TFLG_SET_ORDER (0x3 << 1)
|
||||
|
||||
/* Mask for SET OF or SEQUENCE OF */
|
||||
# define ASN1_TFLG_SK_MASK (0x3 << 1)
|
||||
|
||||
/*
|
||||
* These flags mean the tag should be taken from the tag field. If EXPLICIT
|
||||
* then the underlying type is used for the inner tag.
|
||||
*/
|
||||
|
||||
/* IMPLICIT tagging */
|
||||
# define ASN1_TFLG_IMPTAG (0x1 << 3)
|
||||
|
||||
/* EXPLICIT tagging, inner tag from underlying type */
|
||||
# define ASN1_TFLG_EXPTAG (0x2 << 3)
|
||||
|
||||
# define ASN1_TFLG_TAG_MASK (0x3 << 3)
|
||||
|
||||
/* context specific IMPLICIT */
|
||||
# define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT
|
||||
|
||||
/* context specific EXPLICIT */
|
||||
# define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT
|
||||
|
||||
/*
|
||||
* If tagging is in force these determine the type of tag to use. Otherwise
|
||||
* the tag is determined by the underlying type. These values reflect the
|
||||
* actual octet format.
|
||||
*/
|
||||
|
||||
/* Universal tag */
|
||||
# define ASN1_TFLG_UNIVERSAL (0x0<<6)
|
||||
/* Application tag */
|
||||
# define ASN1_TFLG_APPLICATION (0x1<<6)
|
||||
/* Context specific tag */
|
||||
# define ASN1_TFLG_CONTEXT (0x2<<6)
|
||||
/* Private tag */
|
||||
# define ASN1_TFLG_PRIVATE (0x3<<6)
|
||||
|
||||
# define ASN1_TFLG_TAG_CLASS (0x3<<6)
|
||||
|
||||
/*
|
||||
* These are for ANY DEFINED BY type. In this case the 'item' field points to
|
||||
* an ASN1_ADB structure which contains a table of values to decode the
|
||||
* relevant type
|
||||
*/
|
||||
|
||||
# define ASN1_TFLG_ADB_MASK (0x3<<8)
|
||||
|
||||
# define ASN1_TFLG_ADB_OID (0x1<<8)
|
||||
|
||||
# define ASN1_TFLG_ADB_INT (0x1<<9)
|
||||
|
||||
/*
|
||||
* This flag means a parent structure is passed instead of the field: this is
|
||||
* useful is a SEQUENCE is being combined with a CHOICE for example. Since
|
||||
* this means the structure and item name will differ we need to use the
|
||||
* ASN1_CHOICE_END_name() macro for example.
|
||||
*/
|
||||
|
||||
# define ASN1_TFLG_COMBINE (0x1<<10)
|
||||
|
||||
/*
|
||||
* This flag when present in a SEQUENCE OF, SET OF or EXPLICIT causes
|
||||
* indefinite length constructed encoding to be used if required.
|
||||
*/
|
||||
|
||||
# define ASN1_TFLG_NDEF (0x1<<11)
|
||||
|
||||
/* This is the actual ASN1 item itself */
|
||||
|
||||
struct ASN1_ITEM_st {
|
||||
char itype; /* The item type, primitive, SEQUENCE, CHOICE
|
||||
* or extern */
|
||||
long utype; /* underlying type */
|
||||
const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains
|
||||
* the contents */
|
||||
long tcount; /* Number of templates if SEQUENCE or CHOICE */
|
||||
const void *funcs; /* functions that handle this type */
|
||||
long size; /* Structure size (usually) */
|
||||
# ifndef NO_ASN1_FIELD_NAMES
|
||||
const char *sname; /* Structure name */
|
||||
# endif
|
||||
};
|
||||
|
||||
/*-
|
||||
* These are values for the itype field and
|
||||
* determine how the type is interpreted.
|
||||
*
|
||||
* For PRIMITIVE types the underlying type
|
||||
* determines the behaviour if items is NULL.
|
||||
*
|
||||
* Otherwise templates must contain a single
|
||||
* template and the type is treated in the
|
||||
* same way as the type specified in the template.
|
||||
*
|
||||
* For SEQUENCE types the templates field points
|
||||
* to the members, the size field is the
|
||||
* structure size.
|
||||
*
|
||||
* For CHOICE types the templates field points
|
||||
* to each possible member (typically a union)
|
||||
* and the 'size' field is the offset of the
|
||||
* selector.
|
||||
*
|
||||
* The 'funcs' field is used for application
|
||||
* specific functions.
|
||||
*
|
||||
* For COMPAT types the funcs field gives a
|
||||
* set of functions that handle this type, this
|
||||
* supports the old d2i, i2d convention.
|
||||
*
|
||||
* The EXTERN type uses a new style d2i/i2d.
|
||||
* The new style should be used where possible
|
||||
* because it avoids things like the d2i IMPLICIT
|
||||
* hack.
|
||||
*
|
||||
* MSTRING is a multiple string type, it is used
|
||||
* for a CHOICE of character strings where the
|
||||
* actual strings all occupy an ASN1_STRING
|
||||
* structure. In this case the 'utype' field
|
||||
* has a special meaning, it is used as a mask
|
||||
* of acceptable types using the B_ASN1 constants.
|
||||
*
|
||||
* NDEF_SEQUENCE is the same as SEQUENCE except
|
||||
* that it will use indefinite length constructed
|
||||
* encoding if requested.
|
||||
*
|
||||
*/
|
||||
|
||||
# define ASN1_ITYPE_PRIMITIVE 0x0
|
||||
|
||||
# define ASN1_ITYPE_SEQUENCE 0x1
|
||||
|
||||
# define ASN1_ITYPE_CHOICE 0x2
|
||||
|
||||
# define ASN1_ITYPE_COMPAT 0x3
|
||||
|
||||
# define ASN1_ITYPE_EXTERN 0x4
|
||||
|
||||
# define ASN1_ITYPE_MSTRING 0x5
|
||||
|
||||
# define ASN1_ITYPE_NDEF_SEQUENCE 0x6
|
||||
|
||||
/*
|
||||
* Cache for ASN1 tag and length, so we don't keep re-reading it for things
|
||||
* like CHOICE
|
||||
*/
|
||||
|
||||
struct ASN1_TLC_st {
|
||||
char valid; /* Values below are valid */
|
||||
int ret; /* return value */
|
||||
long plen; /* length */
|
||||
int ptag; /* class value */
|
||||
int pclass; /* class value */
|
||||
int hdrlen; /* header length */
|
||||
};
|
||||
|
||||
/* Typedefs for ASN1 function pointers */
|
||||
|
||||
typedef ASN1_VALUE *ASN1_new_func(void);
|
||||
typedef void ASN1_free_func(ASN1_VALUE *a);
|
||||
typedef ASN1_VALUE *ASN1_d2i_func(ASN1_VALUE **a, const unsigned char **in,
|
||||
long length);
|
||||
typedef int ASN1_i2d_func(ASN1_VALUE *a, unsigned char **in);
|
||||
|
||||
typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
|
||||
const ASN1_ITEM *it, int tag, int aclass, char opt,
|
||||
ASN1_TLC *ctx);
|
||||
|
||||
typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass);
|
||||
typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval,
|
||||
int indent, const char *fname,
|
||||
const ASN1_PCTX *pctx);
|
||||
|
||||
typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont,
|
||||
int *putype, const ASN1_ITEM *it);
|
||||
typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont,
|
||||
int len, int utype, char *free_cont,
|
||||
const ASN1_ITEM *it);
|
||||
typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it, int indent,
|
||||
const ASN1_PCTX *pctx);
|
||||
|
||||
typedef struct ASN1_COMPAT_FUNCS_st {
|
||||
ASN1_new_func *asn1_new;
|
||||
ASN1_free_func *asn1_free;
|
||||
ASN1_d2i_func *asn1_d2i;
|
||||
ASN1_i2d_func *asn1_i2d;
|
||||
} ASN1_COMPAT_FUNCS;
|
||||
|
||||
typedef struct ASN1_EXTERN_FUNCS_st {
|
||||
void *app_data;
|
||||
ASN1_ex_new_func *asn1_ex_new;
|
||||
ASN1_ex_free_func *asn1_ex_free;
|
||||
ASN1_ex_free_func *asn1_ex_clear;
|
||||
ASN1_ex_d2i *asn1_ex_d2i;
|
||||
ASN1_ex_i2d *asn1_ex_i2d;
|
||||
ASN1_ex_print_func *asn1_ex_print;
|
||||
} ASN1_EXTERN_FUNCS;
|
||||
|
||||
typedef struct ASN1_PRIMITIVE_FUNCS_st {
|
||||
void *app_data;
|
||||
unsigned long flags;
|
||||
ASN1_ex_new_func *prim_new;
|
||||
ASN1_ex_free_func *prim_free;
|
||||
ASN1_ex_free_func *prim_clear;
|
||||
ASN1_primitive_c2i *prim_c2i;
|
||||
ASN1_primitive_i2c *prim_i2c;
|
||||
ASN1_primitive_print *prim_print;
|
||||
} ASN1_PRIMITIVE_FUNCS;
|
||||
|
||||
/*
|
||||
* This is the ASN1_AUX structure: it handles various miscellaneous
|
||||
* requirements. For example the use of reference counts and an informational
|
||||
* callback. The "informational callback" is called at various points during
|
||||
* the ASN1 encoding and decoding. It can be used to provide minor
|
||||
* customisation of the structures used. This is most useful where the
|
||||
* supplied routines *almost* do the right thing but need some extra help at
|
||||
* a few points. If the callback returns zero then it is assumed a fatal
|
||||
* error has occurred and the main operation should be abandoned. If major
|
||||
* changes in the default behaviour are required then an external type is
|
||||
* more appropriate.
|
||||
*/
|
||||
|
||||
typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
|
||||
void *exarg);
|
||||
|
||||
typedef struct ASN1_AUX_st {
|
||||
void *app_data;
|
||||
int flags;
|
||||
int ref_offset; /* Offset of reference value */
|
||||
int ref_lock; /* Lock type to use */
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int enc_offset; /* Offset of ASN1_ENCODING structure */
|
||||
} ASN1_AUX;
|
||||
|
||||
/* For print related callbacks exarg points to this structure */
|
||||
typedef struct ASN1_PRINT_ARG_st {
|
||||
BIO *out;
|
||||
int indent;
|
||||
const ASN1_PCTX *pctx;
|
||||
} ASN1_PRINT_ARG;
|
||||
|
||||
/* For streaming related callbacks exarg points to this structure */
|
||||
typedef struct ASN1_STREAM_ARG_st {
|
||||
/* BIO to stream through */
|
||||
BIO *out;
|
||||
/* BIO with filters appended */
|
||||
BIO *ndef_bio;
|
||||
/* Streaming I/O boundary */
|
||||
unsigned char **boundary;
|
||||
} ASN1_STREAM_ARG;
|
||||
|
||||
/* Flags in ASN1_AUX */
|
||||
|
||||
/* Use a reference count */
|
||||
# define ASN1_AFLG_REFCOUNT 1
|
||||
/* Save the encoding of structure (useful for signatures) */
|
||||
# define ASN1_AFLG_ENCODING 2
|
||||
/* The Sequence length is invalid */
|
||||
# define ASN1_AFLG_BROKEN 4
|
||||
|
||||
/* operation values for asn1_cb */
|
||||
|
||||
# define ASN1_OP_NEW_PRE 0
|
||||
# define ASN1_OP_NEW_POST 1
|
||||
# define ASN1_OP_FREE_PRE 2
|
||||
# define ASN1_OP_FREE_POST 3
|
||||
# define ASN1_OP_D2I_PRE 4
|
||||
# define ASN1_OP_D2I_POST 5
|
||||
# define ASN1_OP_I2D_PRE 6
|
||||
# define ASN1_OP_I2D_POST 7
|
||||
# define ASN1_OP_PRINT_PRE 8
|
||||
# define ASN1_OP_PRINT_POST 9
|
||||
# define ASN1_OP_STREAM_PRE 10
|
||||
# define ASN1_OP_STREAM_POST 11
|
||||
# define ASN1_OP_DETACHED_PRE 12
|
||||
# define ASN1_OP_DETACHED_POST 13
|
||||
|
||||
/* Macro to implement a primitive type */
|
||||
# define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
|
||||
# define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
|
||||
ASN1_ITEM_start(itname) \
|
||||
ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
|
||||
ASN1_ITEM_end(itname)
|
||||
|
||||
/* Macro to implement a multi string type */
|
||||
# define IMPLEMENT_ASN1_MSTRING(itname, mask) \
|
||||
ASN1_ITEM_start(itname) \
|
||||
ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
|
||||
ASN1_ITEM_end(itname)
|
||||
|
||||
/* Macro to implement an ASN1_ITEM in terms of old style funcs */
|
||||
|
||||
# define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE)
|
||||
|
||||
# define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \
|
||||
static const ASN1_COMPAT_FUNCS sname##_ff = { \
|
||||
(ASN1_new_func *)sname##_new, \
|
||||
(ASN1_free_func *)sname##_free, \
|
||||
(ASN1_d2i_func *)d2i_##sname, \
|
||||
(ASN1_i2d_func *)i2d_##sname, \
|
||||
}; \
|
||||
ASN1_ITEM_start(sname) \
|
||||
ASN1_ITYPE_COMPAT, \
|
||||
tag, \
|
||||
NULL, \
|
||||
0, \
|
||||
&sname##_ff, \
|
||||
0, \
|
||||
#sname \
|
||||
ASN1_ITEM_end(sname)
|
||||
|
||||
# define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
|
||||
ASN1_ITEM_start(sname) \
|
||||
ASN1_ITYPE_EXTERN, \
|
||||
tag, \
|
||||
NULL, \
|
||||
0, \
|
||||
&fptrs, \
|
||||
0, \
|
||||
#sname \
|
||||
ASN1_ITEM_end(sname)
|
||||
|
||||
/* Macro to implement standard functions in terms of ASN1_ITEM structures */
|
||||
|
||||
# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)
|
||||
|
||||
# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)
|
||||
|
||||
# define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \
|
||||
IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname)
|
||||
|
||||
# define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname)
|
||||
|
||||
# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)
|
||||
|
||||
# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \
|
||||
pre stname *fname##_new(void) \
|
||||
{ \
|
||||
return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
|
||||
} \
|
||||
pre void fname##_free(stname *a) \
|
||||
{ \
|
||||
ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
|
||||
}
|
||||
|
||||
# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \
|
||||
stname *fname##_new(void) \
|
||||
{ \
|
||||
return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
|
||||
} \
|
||||
void fname##_free(stname *a) \
|
||||
{ \
|
||||
ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
|
||||
}
|
||||
|
||||
# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
|
||||
|
||||
# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
|
||||
stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
|
||||
{ \
|
||||
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
|
||||
} \
|
||||
int i2d_##fname(stname *a, unsigned char **out) \
|
||||
{ \
|
||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
|
||||
}
|
||||
|
||||
# define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
|
||||
int i2d_##stname##_NDEF(stname *a, unsigned char **out) \
|
||||
{ \
|
||||
return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
|
||||
}
|
||||
|
||||
/*
|
||||
* This includes evil casts to remove const: they will go away when full ASN1
|
||||
* constification is done.
|
||||
*/
|
||||
# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
|
||||
stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
|
||||
{ \
|
||||
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
|
||||
} \
|
||||
int i2d_##fname(const stname *a, unsigned char **out) \
|
||||
{ \
|
||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
|
||||
}
|
||||
|
||||
# define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
|
||||
stname * stname##_dup(stname *x) \
|
||||
{ \
|
||||
return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
|
||||
}
|
||||
|
||||
# define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \
|
||||
IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
|
||||
|
||||
# define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
|
||||
int fname##_print_ctx(BIO *out, stname *x, int indent, \
|
||||
const ASN1_PCTX *pctx) \
|
||||
{ \
|
||||
return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \
|
||||
ASN1_ITEM_rptr(itname), pctx); \
|
||||
}
|
||||
|
||||
# define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
|
||||
IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
|
||||
|
||||
# define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
|
||||
|
||||
/* external definitions for primitive types */
|
||||
|
||||
DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
|
||||
DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
|
||||
DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
|
||||
DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
|
||||
DECLARE_ASN1_ITEM(CBIGNUM)
|
||||
DECLARE_ASN1_ITEM(BIGNUM)
|
||||
DECLARE_ASN1_ITEM(LONG)
|
||||
DECLARE_ASN1_ITEM(ZLONG)
|
||||
|
||||
DECLARE_STACK_OF(ASN1_VALUE)
|
||||
|
||||
/* Functions used internally by the ASN1 code */
|
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
|
||||
const ASN1_TEMPLATE *tt);
|
||||
int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
|
||||
const ASN1_ITEM *it, int tag, int aclass, char opt,
|
||||
ASN1_TLC *ctx);
|
||||
|
||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass);
|
||||
int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_TEMPLATE *tt);
|
||||
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
|
||||
const ASN1_ITEM *it);
|
||||
|
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
|
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
|
||||
int nullerr);
|
||||
|
||||
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
|
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it);
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
|
||||
const ASN1_ITEM *it);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
553
cms/lib/cms.h
Normal file
553
cms/lib/cms.h
Normal file
|
@ -0,0 +1,553 @@
|
|||
/* crypto/cms/cms.h */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#ifndef HEADER_CMS_H
|
||||
# define HEADER_CMS_H
|
||||
|
||||
#include "libressl_cms.h"
|
||||
#include "libressl_evp.h"
|
||||
# include <openssl/x509.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct CMS_ContentInfo_st CMS_ContentInfo;
|
||||
typedef struct CMS_SignerInfo_st CMS_SignerInfo;
|
||||
typedef struct CMS_CertificateChoices CMS_CertificateChoices;
|
||||
typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice;
|
||||
typedef struct CMS_RecipientInfo_st CMS_RecipientInfo;
|
||||
typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest;
|
||||
typedef struct CMS_Receipt_st CMS_Receipt;
|
||||
typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey;
|
||||
typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute;
|
||||
|
||||
DECLARE_STACK_OF(CMS_SignerInfo)
|
||||
DECLARE_STACK_OF(GENERAL_NAMES)
|
||||
DECLARE_STACK_OF(CMS_RecipientEncryptedKey)
|
||||
DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
|
||||
DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
|
||||
DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
|
||||
|
||||
# define CMS_SIGNERINFO_ISSUER_SERIAL 0
|
||||
# define CMS_SIGNERINFO_KEYIDENTIFIER 1
|
||||
|
||||
# define CMS_RECIPINFO_NONE -1
|
||||
# define CMS_RECIPINFO_TRANS 0
|
||||
# define CMS_RECIPINFO_AGREE 1
|
||||
# define CMS_RECIPINFO_KEK 2
|
||||
# define CMS_RECIPINFO_PASS 3
|
||||
# define CMS_RECIPINFO_OTHER 4
|
||||
|
||||
/* S/MIME related flags */
|
||||
|
||||
# define CMS_TEXT 0x1
|
||||
# define CMS_NOCERTS 0x2
|
||||
# define CMS_NO_CONTENT_VERIFY 0x4
|
||||
# define CMS_NO_ATTR_VERIFY 0x8
|
||||
# define CMS_NOSIGS \
|
||||
(CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY)
|
||||
# define CMS_NOINTERN 0x10
|
||||
# define CMS_NO_SIGNER_CERT_VERIFY 0x20
|
||||
# define CMS_NOVERIFY 0x20
|
||||
# define CMS_DETACHED 0x40
|
||||
# define CMS_BINARY 0x80
|
||||
# define CMS_NOATTR 0x100
|
||||
# define CMS_NOSMIMECAP 0x200
|
||||
# define CMS_NOOLDMIMETYPE 0x400
|
||||
# define CMS_CRLFEOL 0x800
|
||||
# define CMS_STREAM 0x1000
|
||||
# define CMS_NOCRL 0x2000
|
||||
# define CMS_PARTIAL 0x4000
|
||||
# define CMS_REUSE_DIGEST 0x8000
|
||||
# define CMS_USE_KEYID 0x10000
|
||||
# define CMS_DEBUG_DECRYPT 0x20000
|
||||
# define CMS_KEY_PARAM 0x40000
|
||||
|
||||
const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
|
||||
|
||||
BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont);
|
||||
int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio);
|
||||
|
||||
ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms);
|
||||
int CMS_is_detached(CMS_ContentInfo *cms);
|
||||
int CMS_set_detached(CMS_ContentInfo *cms, int detached);
|
||||
|
||||
# ifdef HEADER_PEM_H
|
||||
DECLARE_PEM_rw_const(CMS, CMS_ContentInfo)
|
||||
# endif
|
||||
int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms);
|
||||
CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms);
|
||||
int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms);
|
||||
|
||||
BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms);
|
||||
int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags);
|
||||
int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in,
|
||||
int flags);
|
||||
CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont);
|
||||
int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags);
|
||||
|
||||
int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
|
||||
unsigned int flags);
|
||||
|
||||
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
|
||||
STACK_OF(X509) *certs, BIO *data,
|
||||
unsigned int flags);
|
||||
|
||||
CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
|
||||
X509 *signcert, EVP_PKEY *pkey,
|
||||
STACK_OF(X509) *certs, unsigned int flags);
|
||||
|
||||
int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
|
||||
CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
|
||||
|
||||
int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
||||
unsigned int flags);
|
||||
CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
|
||||
unsigned int flags);
|
||||
|
||||
int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
|
||||
const unsigned char *key, size_t keylen,
|
||||
BIO *dcont, BIO *out, unsigned int flags);
|
||||
|
||||
CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
|
||||
const unsigned char *key,
|
||||
size_t keylen, unsigned int flags);
|
||||
|
||||
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
|
||||
const unsigned char *key, size_t keylen);
|
||||
|
||||
int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
||||
X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags);
|
||||
|
||||
int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
|
||||
STACK_OF(X509) *certs,
|
||||
X509_STORE *store, unsigned int flags);
|
||||
|
||||
STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
|
||||
|
||||
CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
|
||||
const EVP_CIPHER *cipher, unsigned int flags);
|
||||
|
||||
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
|
||||
BIO *dcont, BIO *out, unsigned int flags);
|
||||
|
||||
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
|
||||
int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
|
||||
unsigned char *key, size_t keylen,
|
||||
unsigned char *id, size_t idlen);
|
||||
int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
|
||||
unsigned char *pass, ossl_ssize_t passlen);
|
||||
|
||||
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
|
||||
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
|
||||
EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
|
||||
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
|
||||
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
|
||||
X509 *recip, unsigned int flags);
|
||||
int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
|
||||
int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
|
||||
int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
|
||||
EVP_PKEY **pk, X509 **recip,
|
||||
X509_ALGOR **palg);
|
||||
int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer,
|
||||
ASN1_INTEGER **sno);
|
||||
|
||||
CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
|
||||
unsigned char *key, size_t keylen,
|
||||
unsigned char *id, size_t idlen,
|
||||
ASN1_GENERALIZEDTIME *date,
|
||||
ASN1_OBJECT *otherTypeId,
|
||||
ASN1_TYPE *otherType);
|
||||
|
||||
int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
|
||||
X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pid,
|
||||
ASN1_GENERALIZEDTIME **pdate,
|
||||
ASN1_OBJECT **potherid,
|
||||
ASN1_TYPE **pothertype);
|
||||
|
||||
int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
|
||||
unsigned char *key, size_t keylen);
|
||||
|
||||
int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
|
||||
const unsigned char *id, size_t idlen);
|
||||
|
||||
int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
|
||||
unsigned char *pass,
|
||||
ossl_ssize_t passlen);
|
||||
|
||||
CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
|
||||
int iter, int wrap_nid,
|
||||
int pbe_nid,
|
||||
unsigned char *pass,
|
||||
ossl_ssize_t passlen,
|
||||
const EVP_CIPHER *kekciph);
|
||||
|
||||
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
|
||||
int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
|
||||
|
||||
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
||||
unsigned int flags);
|
||||
CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags);
|
||||
|
||||
int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid);
|
||||
const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms);
|
||||
|
||||
CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms);
|
||||
int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert);
|
||||
int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert);
|
||||
STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms);
|
||||
|
||||
CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms);
|
||||
int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl);
|
||||
int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl);
|
||||
STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms);
|
||||
|
||||
int CMS_SignedData_init(CMS_ContentInfo *cms);
|
||||
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
|
||||
X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
|
||||
unsigned int flags);
|
||||
EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si);
|
||||
EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si);
|
||||
STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms);
|
||||
|
||||
void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer);
|
||||
int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer, ASN1_INTEGER **sno);
|
||||
int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert);
|
||||
int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
||||
unsigned int flags);
|
||||
void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
|
||||
X509 **signer, X509_ALGOR **pdig,
|
||||
X509_ALGOR **psig);
|
||||
ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si);
|
||||
int CMS_SignerInfo_sign(CMS_SignerInfo *si);
|
||||
int CMS_SignerInfo_verify(CMS_SignerInfo *si);
|
||||
int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain);
|
||||
|
||||
int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs);
|
||||
int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
|
||||
int algnid, int keysize);
|
||||
int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap);
|
||||
|
||||
int CMS_signed_get_attr_count(const CMS_SignerInfo *si);
|
||||
int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
|
||||
int lastpos);
|
||||
int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
|
||||
int lastpos);
|
||||
X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc);
|
||||
X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc);
|
||||
int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
|
||||
int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
|
||||
const ASN1_OBJECT *obj, int type,
|
||||
const void *bytes, int len);
|
||||
int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
|
||||
int nid, int type,
|
||||
const void *bytes, int len);
|
||||
int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
|
||||
const char *attrname, int type,
|
||||
const void *bytes, int len);
|
||||
void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
|
||||
int lastpos, int type);
|
||||
|
||||
int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si);
|
||||
int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
|
||||
int lastpos);
|
||||
int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
|
||||
int lastpos);
|
||||
X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc);
|
||||
X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc);
|
||||
int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
|
||||
int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
|
||||
const ASN1_OBJECT *obj, int type,
|
||||
const void *bytes, int len);
|
||||
int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
|
||||
int nid, int type,
|
||||
const void *bytes, int len);
|
||||
int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
|
||||
const char *attrname, int type,
|
||||
const void *bytes, int len);
|
||||
void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
|
||||
int lastpos, int type);
|
||||
|
||||
# ifdef HEADER_X509V3_H
|
||||
|
||||
int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
|
||||
CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
|
||||
int allorfirst,
|
||||
STACK_OF(GENERAL_NAMES)
|
||||
*receiptList, STACK_OF(GENERAL_NAMES)
|
||||
*receiptsTo);
|
||||
int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
|
||||
void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
|
||||
ASN1_STRING **pcid,
|
||||
int *pallorfirst,
|
||||
STACK_OF(GENERAL_NAMES) **plist,
|
||||
STACK_OF(GENERAL_NAMES) **prto);
|
||||
# endif
|
||||
int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
|
||||
X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pukm);
|
||||
STACK_OF(CMS_RecipientEncryptedKey)
|
||||
*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri);
|
||||
|
||||
int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
|
||||
X509_ALGOR **pubalg,
|
||||
ASN1_BIT_STRING **pubkey,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer,
|
||||
ASN1_INTEGER **sno);
|
||||
|
||||
int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert);
|
||||
|
||||
int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
ASN1_GENERALIZEDTIME **tm,
|
||||
CMS_OtherKeyAttribute **other,
|
||||
X509_NAME **issuer, ASN1_INTEGER **sno);
|
||||
int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
|
||||
X509 *cert);
|
||||
int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
|
||||
EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri);
|
||||
int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri,
|
||||
CMS_RecipientEncryptedKey *rek);
|
||||
|
||||
int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
|
||||
ASN1_OCTET_STRING *ukm, int keylen);
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
/*
|
||||
* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
* made after this point may be overwritten when the script is next run.
|
||||
*/
|
||||
void ERR_load_CMS_strings(void);
|
||||
|
||||
/* Error codes for the CMS functions. */
|
||||
|
||||
/* Function codes. */
|
||||
# define CMS_F_CHECK_CONTENT 99
|
||||
# define CMS_F_CMS_ADD0_CERT 164
|
||||
# define CMS_F_CMS_ADD0_RECIPIENT_KEY 100
|
||||
# define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165
|
||||
# define CMS_F_CMS_ADD1_RECEIPTREQUEST 158
|
||||
# define CMS_F_CMS_ADD1_RECIPIENT_CERT 101
|
||||
# define CMS_F_CMS_ADD1_SIGNER 102
|
||||
# define CMS_F_CMS_ADD1_SIGNINGTIME 103
|
||||
# define CMS_F_CMS_COMPRESS 104
|
||||
# define CMS_F_CMS_COMPRESSEDDATA_CREATE 105
|
||||
# define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 106
|
||||
# define CMS_F_CMS_COPY_CONTENT 107
|
||||
# define CMS_F_CMS_COPY_MESSAGEDIGEST 108
|
||||
# define CMS_F_CMS_DATA 109
|
||||
# define CMS_F_CMS_DATAFINAL 110
|
||||
# define CMS_F_CMS_DATAINIT 111
|
||||
# define CMS_F_CMS_DECRYPT 112
|
||||
# define CMS_F_CMS_DECRYPT_SET1_KEY 113
|
||||
# define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166
|
||||
# define CMS_F_CMS_DECRYPT_SET1_PKEY 114
|
||||
# define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115
|
||||
# define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116
|
||||
# define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117
|
||||
# define CMS_F_CMS_DIGEST_VERIFY 118
|
||||
# define CMS_F_CMS_ENCODE_RECEIPT 161
|
||||
# define CMS_F_CMS_ENCRYPT 119
|
||||
# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120
|
||||
# define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121
|
||||
# define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122
|
||||
# define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123
|
||||
# define CMS_F_CMS_ENVELOPEDDATA_CREATE 124
|
||||
# define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125
|
||||
# define CMS_F_CMS_ENVELOPED_DATA_INIT 126
|
||||
# define CMS_F_CMS_ENV_ASN1_CTRL 171
|
||||
# define CMS_F_CMS_FINAL 127
|
||||
# define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128
|
||||
# define CMS_F_CMS_GET0_CONTENT 129
|
||||
# define CMS_F_CMS_GET0_ECONTENT_TYPE 130
|
||||
# define CMS_F_CMS_GET0_ENVELOPED 131
|
||||
# define CMS_F_CMS_GET0_REVOCATION_CHOICES 132
|
||||
# define CMS_F_CMS_GET0_SIGNED 133
|
||||
# define CMS_F_CMS_MSGSIGDIGEST_ADD1 162
|
||||
# define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159
|
||||
# define CMS_F_CMS_RECEIPT_VERIFY 160
|
||||
# define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134
|
||||
# define CMS_F_CMS_RECIPIENTINFO_ENCRYPT 169
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT 178
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG 175
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID 173
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS 172
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP 174
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 135
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 136
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 137
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 138
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 139
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 140
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142
|
||||
# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143
|
||||
# define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 167
|
||||
# define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144
|
||||
# define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168
|
||||
# define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145
|
||||
# define CMS_F_CMS_SD_ASN1_CTRL 170
|
||||
# define CMS_F_CMS_SET1_IAS 176
|
||||
# define CMS_F_CMS_SET1_KEYID 177
|
||||
# define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146
|
||||
# define CMS_F_CMS_SET_DETACHED 147
|
||||
# define CMS_F_CMS_SIGN 148
|
||||
# define CMS_F_CMS_SIGNED_DATA_INIT 149
|
||||
# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 150
|
||||
# define CMS_F_CMS_SIGNERINFO_SIGN 151
|
||||
# define CMS_F_CMS_SIGNERINFO_VERIFY 152
|
||||
# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153
|
||||
# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154
|
||||
# define CMS_F_CMS_SIGN_RECEIPT 163
|
||||
# define CMS_F_CMS_STREAM 155
|
||||
# define CMS_F_CMS_UNCOMPRESS 156
|
||||
# define CMS_F_CMS_VERIFY 157
|
||||
|
||||
/* Reason codes. */
|
||||
# define CMS_R_ADD_SIGNER_ERROR 99
|
||||
# define CMS_R_CERTIFICATE_ALREADY_PRESENT 175
|
||||
# define CMS_R_CERTIFICATE_HAS_NO_KEYID 160
|
||||
# define CMS_R_CERTIFICATE_VERIFY_ERROR 100
|
||||
# define CMS_R_CIPHER_INITIALISATION_ERROR 101
|
||||
# define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102
|
||||
# define CMS_R_CMS_DATAFINAL_ERROR 103
|
||||
# define CMS_R_CMS_LIB 104
|
||||
# define CMS_R_CONTENTIDENTIFIER_MISMATCH 170
|
||||
# define CMS_R_CONTENT_NOT_FOUND 105
|
||||
# define CMS_R_CONTENT_TYPE_MISMATCH 171
|
||||
# define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 106
|
||||
# define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 107
|
||||
# define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 108
|
||||
# define CMS_R_CONTENT_VERIFY_ERROR 109
|
||||
# define CMS_R_CTRL_ERROR 110
|
||||
# define CMS_R_CTRL_FAILURE 111
|
||||
# define CMS_R_DECRYPT_ERROR 112
|
||||
# define CMS_R_DIGEST_ERROR 161
|
||||
# define CMS_R_ERROR_GETTING_PUBLIC_KEY 113
|
||||
# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114
|
||||
# define CMS_R_ERROR_SETTING_KEY 115
|
||||
# define CMS_R_ERROR_SETTING_RECIPIENTINFO 116
|
||||
# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117
|
||||
# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176
|
||||
# define CMS_R_INVALID_KEY_LENGTH 118
|
||||
# define CMS_R_MD_BIO_INIT_ERROR 119
|
||||
# define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120
|
||||
# define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121
|
||||
# define CMS_R_MSGSIGDIGEST_ERROR 172
|
||||
# define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE 162
|
||||
# define CMS_R_MSGSIGDIGEST_WRONG_LENGTH 163
|
||||
# define CMS_R_NEED_ONE_SIGNER 164
|
||||
# define CMS_R_NOT_A_SIGNED_RECEIPT 165
|
||||
# define CMS_R_NOT_ENCRYPTED_DATA 122
|
||||
# define CMS_R_NOT_KEK 123
|
||||
# define CMS_R_NOT_KEY_AGREEMENT 181
|
||||
# define CMS_R_NOT_KEY_TRANSPORT 124
|
||||
# define CMS_R_NOT_PWRI 177
|
||||
# define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125
|
||||
# define CMS_R_NO_CIPHER 126
|
||||
# define CMS_R_NO_CONTENT 127
|
||||
# define CMS_R_NO_CONTENT_TYPE 173
|
||||
# define CMS_R_NO_DEFAULT_DIGEST 128
|
||||
# define CMS_R_NO_DIGEST_SET 129
|
||||
# define CMS_R_NO_KEY 130
|
||||
# define CMS_R_NO_KEY_OR_CERT 174
|
||||
# define CMS_R_NO_MATCHING_DIGEST 131
|
||||
# define CMS_R_NO_MATCHING_RECIPIENT 132
|
||||
# define CMS_R_NO_MATCHING_SIGNATURE 166
|
||||
# define CMS_R_NO_MSGSIGDIGEST 167
|
||||
# define CMS_R_NO_PASSWORD 178
|
||||
# define CMS_R_NO_PRIVATE_KEY 133
|
||||
# define CMS_R_NO_PUBLIC_KEY 134
|
||||
# define CMS_R_NO_RECEIPT_REQUEST 168
|
||||
# define CMS_R_NO_SIGNERS 135
|
||||
# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136
|
||||
# define CMS_R_RECEIPT_DECODE_ERROR 169
|
||||
# define CMS_R_RECIPIENT_ERROR 137
|
||||
# define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138
|
||||
# define CMS_R_SIGNFINAL_ERROR 139
|
||||
# define CMS_R_SMIME_TEXT_ERROR 140
|
||||
# define CMS_R_STORE_INIT_ERROR 141
|
||||
# define CMS_R_TYPE_NOT_COMPRESSED_DATA 142
|
||||
# define CMS_R_TYPE_NOT_DATA 143
|
||||
# define CMS_R_TYPE_NOT_DIGESTED_DATA 144
|
||||
# define CMS_R_TYPE_NOT_ENCRYPTED_DATA 145
|
||||
# define CMS_R_TYPE_NOT_ENVELOPED_DATA 146
|
||||
# define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 147
|
||||
# define CMS_R_UNKNOWN_CIPHER 148
|
||||
# define CMS_R_UNKNOWN_DIGEST_ALGORIHM 149
|
||||
# define CMS_R_UNKNOWN_ID 150
|
||||
# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151
|
||||
# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152
|
||||
# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153
|
||||
# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179
|
||||
# define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154
|
||||
# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE 155
|
||||
# define CMS_R_UNSUPPORTED_TYPE 156
|
||||
# define CMS_R_UNWRAP_ERROR 157
|
||||
# define CMS_R_UNWRAP_FAILURE 180
|
||||
# define CMS_R_VERIFICATION_FAILURE 158
|
||||
# define CMS_R_WRAP_ERROR 159
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
459
cms/lib/cms_asn1.c
Normal file
459
cms/lib/cms_asn1.c
Normal file
|
@ -0,0 +1,459 @@
|
|||
/* crypto/cms/cms_asn1.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
|
||||
|
||||
ASN1_SEQUENCE(CMS_IssuerAndSerialNumber) = {
|
||||
ASN1_SIMPLE(CMS_IssuerAndSerialNumber, issuer, X509_NAME),
|
||||
ASN1_SIMPLE(CMS_IssuerAndSerialNumber, serialNumber, ASN1_INTEGER)
|
||||
} ASN1_SEQUENCE_END(CMS_IssuerAndSerialNumber)
|
||||
|
||||
ASN1_SEQUENCE(CMS_OtherCertificateFormat) = {
|
||||
ASN1_SIMPLE(CMS_OtherCertificateFormat, otherCertFormat, ASN1_OBJECT),
|
||||
ASN1_OPT(CMS_OtherCertificateFormat, otherCert, ASN1_ANY)
|
||||
} ASN1_SEQUENCE_END(CMS_OtherCertificateFormat)
|
||||
|
||||
ASN1_CHOICE(CMS_CertificateChoices) = {
|
||||
ASN1_SIMPLE(CMS_CertificateChoices, d.certificate, X509),
|
||||
ASN1_IMP(CMS_CertificateChoices, d.extendedCertificate, ASN1_SEQUENCE, 0),
|
||||
ASN1_IMP(CMS_CertificateChoices, d.v1AttrCert, ASN1_SEQUENCE, 1),
|
||||
ASN1_IMP(CMS_CertificateChoices, d.v2AttrCert, ASN1_SEQUENCE, 2),
|
||||
ASN1_IMP(CMS_CertificateChoices, d.other, CMS_OtherCertificateFormat, 3)
|
||||
} ASN1_CHOICE_END(CMS_CertificateChoices)
|
||||
|
||||
ASN1_CHOICE(CMS_SignerIdentifier) = {
|
||||
ASN1_SIMPLE(CMS_SignerIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
|
||||
ASN1_IMP(CMS_SignerIdentifier, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0)
|
||||
} ASN1_CHOICE_END(CMS_SignerIdentifier)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_EncapsulatedContentInfo) = {
|
||||
ASN1_SIMPLE(CMS_EncapsulatedContentInfo, eContentType, ASN1_OBJECT),
|
||||
ASN1_NDEF_EXP_OPT(CMS_EncapsulatedContentInfo, eContent, ASN1_OCTET_STRING_NDEF, 0)
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_EncapsulatedContentInfo)
|
||||
|
||||
/* Minor tweak to operation: free up signer key, cert */
|
||||
static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
if (operation == ASN1_OP_FREE_POST) {
|
||||
CMS_SignerInfo *si = (CMS_SignerInfo *)*pval;
|
||||
if (si->pkey)
|
||||
EVP_PKEY_free(si->pkey);
|
||||
if (si->signer)
|
||||
X509_free(si->signer);
|
||||
if (si->pctx)
|
||||
EVP_MD_CTX_cleanup(&si->mctx);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(CMS_SignerInfo, cms_si_cb) = {
|
||||
ASN1_SIMPLE(CMS_SignerInfo, version, LONG),
|
||||
ASN1_SIMPLE(CMS_SignerInfo, sid, CMS_SignerIdentifier),
|
||||
ASN1_SIMPLE(CMS_SignerInfo, digestAlgorithm, X509_ALGOR),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, signedAttrs, X509_ATTRIBUTE, 0),
|
||||
ASN1_SIMPLE(CMS_SignerInfo, signatureAlgorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_SignerInfo, signature, ASN1_OCTET_STRING),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, unsignedAttrs, X509_ATTRIBUTE, 1)
|
||||
} ASN1_SEQUENCE_END_cb(CMS_SignerInfo, CMS_SignerInfo)
|
||||
|
||||
ASN1_SEQUENCE(CMS_OtherRevocationInfoFormat) = {
|
||||
ASN1_SIMPLE(CMS_OtherRevocationInfoFormat, otherRevInfoFormat, ASN1_OBJECT),
|
||||
ASN1_OPT(CMS_OtherRevocationInfoFormat, otherRevInfo, ASN1_ANY)
|
||||
} ASN1_SEQUENCE_END(CMS_OtherRevocationInfoFormat)
|
||||
|
||||
ASN1_CHOICE(CMS_RevocationInfoChoice) = {
|
||||
ASN1_SIMPLE(CMS_RevocationInfoChoice, d.crl, X509_CRL),
|
||||
ASN1_IMP(CMS_RevocationInfoChoice, d.other, CMS_OtherRevocationInfoFormat, 1)
|
||||
} ASN1_CHOICE_END(CMS_RevocationInfoChoice)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_SignedData) = {
|
||||
ASN1_SIMPLE(CMS_SignedData, version, LONG),
|
||||
ASN1_SET_OF(CMS_SignedData, digestAlgorithms, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_SignedData, encapContentInfo, CMS_EncapsulatedContentInfo),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_SignedData, certificates, CMS_CertificateChoices, 0),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1),
|
||||
ASN1_SET_OF(CMS_SignedData, signerInfos, CMS_SignerInfo)
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_SignedData)
|
||||
|
||||
ASN1_SEQUENCE(CMS_OriginatorInfo) = {
|
||||
ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, certificates, CMS_CertificateChoices, 0),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, crls, CMS_RevocationInfoChoice, 1)
|
||||
} ASN1_SEQUENCE_END(CMS_OriginatorInfo)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = {
|
||||
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT),
|
||||
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR),
|
||||
ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0)
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo)
|
||||
|
||||
ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = {
|
||||
ASN1_SIMPLE(CMS_KeyTransRecipientInfo, version, LONG),
|
||||
ASN1_SIMPLE(CMS_KeyTransRecipientInfo, rid, CMS_SignerIdentifier),
|
||||
ASN1_SIMPLE(CMS_KeyTransRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_KeyTransRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END(CMS_KeyTransRecipientInfo)
|
||||
|
||||
ASN1_SEQUENCE(CMS_OtherKeyAttribute) = {
|
||||
ASN1_SIMPLE(CMS_OtherKeyAttribute, keyAttrId, ASN1_OBJECT),
|
||||
ASN1_OPT(CMS_OtherKeyAttribute, keyAttr, ASN1_ANY)
|
||||
} ASN1_SEQUENCE_END(CMS_OtherKeyAttribute)
|
||||
|
||||
ASN1_SEQUENCE(CMS_RecipientKeyIdentifier) = {
|
||||
ASN1_SIMPLE(CMS_RecipientKeyIdentifier, subjectKeyIdentifier, ASN1_OCTET_STRING),
|
||||
ASN1_OPT(CMS_RecipientKeyIdentifier, date, ASN1_GENERALIZEDTIME),
|
||||
ASN1_OPT(CMS_RecipientKeyIdentifier, other, CMS_OtherKeyAttribute)
|
||||
} ASN1_SEQUENCE_END(CMS_RecipientKeyIdentifier)
|
||||
|
||||
ASN1_CHOICE(CMS_KeyAgreeRecipientIdentifier) = {
|
||||
ASN1_SIMPLE(CMS_KeyAgreeRecipientIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
|
||||
ASN1_IMP(CMS_KeyAgreeRecipientIdentifier, d.rKeyId, CMS_RecipientKeyIdentifier, 0)
|
||||
} ASN1_CHOICE_END(CMS_KeyAgreeRecipientIdentifier)
|
||||
|
||||
static int cms_rek_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
CMS_RecipientEncryptedKey *rek = (CMS_RecipientEncryptedKey *)*pval;
|
||||
if (operation == ASN1_OP_FREE_POST) {
|
||||
if (rek->pkey)
|
||||
EVP_PKEY_free(rek->pkey);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(CMS_RecipientEncryptedKey, cms_rek_cb) = {
|
||||
ASN1_SIMPLE(CMS_RecipientEncryptedKey, rid, CMS_KeyAgreeRecipientIdentifier),
|
||||
ASN1_SIMPLE(CMS_RecipientEncryptedKey, encryptedKey, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END_cb(CMS_RecipientEncryptedKey, CMS_RecipientEncryptedKey)
|
||||
|
||||
ASN1_SEQUENCE(CMS_OriginatorPublicKey) = {
|
||||
ASN1_SIMPLE(CMS_OriginatorPublicKey, algorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_OriginatorPublicKey, publicKey, ASN1_BIT_STRING)
|
||||
} ASN1_SEQUENCE_END(CMS_OriginatorPublicKey)
|
||||
|
||||
ASN1_CHOICE(CMS_OriginatorIdentifierOrKey) = {
|
||||
ASN1_SIMPLE(CMS_OriginatorIdentifierOrKey, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
|
||||
ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0),
|
||||
ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.originatorKey, CMS_OriginatorPublicKey, 1)
|
||||
} ASN1_CHOICE_END(CMS_OriginatorIdentifierOrKey)
|
||||
|
||||
static int cms_kari_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
CMS_KeyAgreeRecipientInfo *kari = (CMS_KeyAgreeRecipientInfo *)*pval;
|
||||
if (operation == ASN1_OP_NEW_POST) {
|
||||
EVP_CIPHER_CTX_init(&kari->ctx);
|
||||
EVP_CIPHER_CTX_set_flags(&kari->ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
||||
kari->pctx = NULL;
|
||||
} else if (operation == ASN1_OP_FREE_POST) {
|
||||
if (kari->pctx)
|
||||
EVP_PKEY_CTX_free(kari->pctx);
|
||||
EVP_CIPHER_CTX_cleanup(&kari->ctx);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(CMS_KeyAgreeRecipientInfo, cms_kari_cb) = {
|
||||
ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, version, LONG),
|
||||
ASN1_EXP(CMS_KeyAgreeRecipientInfo, originator, CMS_OriginatorIdentifierOrKey, 0),
|
||||
ASN1_EXP_OPT(CMS_KeyAgreeRecipientInfo, ukm, ASN1_OCTET_STRING, 1),
|
||||
ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
|
||||
ASN1_SEQUENCE_OF(CMS_KeyAgreeRecipientInfo, recipientEncryptedKeys, CMS_RecipientEncryptedKey)
|
||||
} ASN1_SEQUENCE_END_cb(CMS_KeyAgreeRecipientInfo, CMS_KeyAgreeRecipientInfo)
|
||||
|
||||
ASN1_SEQUENCE(CMS_KEKIdentifier) = {
|
||||
ASN1_SIMPLE(CMS_KEKIdentifier, keyIdentifier, ASN1_OCTET_STRING),
|
||||
ASN1_OPT(CMS_KEKIdentifier, date, ASN1_GENERALIZEDTIME),
|
||||
ASN1_OPT(CMS_KEKIdentifier, other, CMS_OtherKeyAttribute)
|
||||
} ASN1_SEQUENCE_END(CMS_KEKIdentifier)
|
||||
|
||||
ASN1_SEQUENCE(CMS_KEKRecipientInfo) = {
|
||||
ASN1_SIMPLE(CMS_KEKRecipientInfo, version, LONG),
|
||||
ASN1_SIMPLE(CMS_KEKRecipientInfo, kekid, CMS_KEKIdentifier),
|
||||
ASN1_SIMPLE(CMS_KEKRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_KEKRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END(CMS_KEKRecipientInfo)
|
||||
|
||||
ASN1_SEQUENCE(CMS_PasswordRecipientInfo) = {
|
||||
ASN1_SIMPLE(CMS_PasswordRecipientInfo, version, LONG),
|
||||
ASN1_IMP_OPT(CMS_PasswordRecipientInfo, keyDerivationAlgorithm, X509_ALGOR, 0),
|
||||
ASN1_SIMPLE(CMS_PasswordRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_PasswordRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END(CMS_PasswordRecipientInfo)
|
||||
|
||||
ASN1_SEQUENCE(CMS_OtherRecipientInfo) = {
|
||||
ASN1_SIMPLE(CMS_OtherRecipientInfo, oriType, ASN1_OBJECT),
|
||||
ASN1_OPT(CMS_OtherRecipientInfo, oriValue, ASN1_ANY)
|
||||
} ASN1_SEQUENCE_END(CMS_OtherRecipientInfo)
|
||||
|
||||
/* Free up RecipientInfo additional data */
|
||||
static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
if (operation == ASN1_OP_FREE_PRE) {
|
||||
CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval;
|
||||
if (ri->type == CMS_RECIPINFO_TRANS) {
|
||||
CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
|
||||
if (ktri->pkey)
|
||||
EVP_PKEY_free(ktri->pkey);
|
||||
if (ktri->recip)
|
||||
X509_free(ktri->recip);
|
||||
if (ktri->pctx)
|
||||
EVP_PKEY_CTX_free(ktri->pctx);
|
||||
} else if (ri->type == CMS_RECIPINFO_KEK) {
|
||||
CMS_KEKRecipientInfo *kekri = ri->d.kekri;
|
||||
if (kekri->key) {
|
||||
OPENSSL_cleanse(kekri->key, kekri->keylen);
|
||||
OPENSSL_free(kekri->key);
|
||||
}
|
||||
} else if (ri->type == CMS_RECIPINFO_PASS) {
|
||||
CMS_PasswordRecipientInfo *pwri = ri->d.pwri;
|
||||
if (pwri->pass) {
|
||||
OPENSSL_cleanse(pwri->pass, pwri->passlen);
|
||||
OPENSSL_free(pwri->pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_CHOICE_cb(CMS_RecipientInfo, cms_ri_cb) = {
|
||||
ASN1_SIMPLE(CMS_RecipientInfo, d.ktri, CMS_KeyTransRecipientInfo),
|
||||
ASN1_IMP(CMS_RecipientInfo, d.kari, CMS_KeyAgreeRecipientInfo, 1),
|
||||
ASN1_IMP(CMS_RecipientInfo, d.kekri, CMS_KEKRecipientInfo, 2),
|
||||
ASN1_IMP(CMS_RecipientInfo, d.pwri, CMS_PasswordRecipientInfo, 3),
|
||||
ASN1_IMP(CMS_RecipientInfo, d.ori, CMS_OtherRecipientInfo, 4)
|
||||
} ASN1_CHOICE_END_cb(CMS_RecipientInfo, CMS_RecipientInfo, type)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = {
|
||||
ASN1_SIMPLE(CMS_EnvelopedData, version, LONG),
|
||||
ASN1_IMP_OPT(CMS_EnvelopedData, originatorInfo, CMS_OriginatorInfo, 0),
|
||||
ASN1_SET_OF(CMS_EnvelopedData, recipientInfos, CMS_RecipientInfo),
|
||||
ASN1_SIMPLE(CMS_EnvelopedData, encryptedContentInfo, CMS_EncryptedContentInfo),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_EnvelopedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_EnvelopedData)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_DigestedData) = {
|
||||
ASN1_SIMPLE(CMS_DigestedData, version, LONG),
|
||||
ASN1_SIMPLE(CMS_DigestedData, digestAlgorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_DigestedData, encapContentInfo, CMS_EncapsulatedContentInfo),
|
||||
ASN1_SIMPLE(CMS_DigestedData, digest, ASN1_OCTET_STRING)
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_DigestedData)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_EncryptedData) = {
|
||||
ASN1_SIMPLE(CMS_EncryptedData, version, LONG),
|
||||
ASN1_SIMPLE(CMS_EncryptedData, encryptedContentInfo, CMS_EncryptedContentInfo),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_EncryptedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedData)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = {
|
||||
ASN1_SIMPLE(CMS_AuthenticatedData, version, LONG),
|
||||
ASN1_IMP_OPT(CMS_AuthenticatedData, originatorInfo, CMS_OriginatorInfo, 0),
|
||||
ASN1_SET_OF(CMS_AuthenticatedData, recipientInfos, CMS_RecipientInfo),
|
||||
ASN1_SIMPLE(CMS_AuthenticatedData, macAlgorithm, X509_ALGOR),
|
||||
ASN1_IMP(CMS_AuthenticatedData, digestAlgorithm, X509_ALGOR, 1),
|
||||
ASN1_SIMPLE(CMS_AuthenticatedData, encapContentInfo, CMS_EncapsulatedContentInfo),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ALGOR, 2),
|
||||
ASN1_SIMPLE(CMS_AuthenticatedData, mac, ASN1_OCTET_STRING),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ALGOR, 3)
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_AuthenticatedData)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(CMS_CompressedData) = {
|
||||
ASN1_SIMPLE(CMS_CompressedData, version, LONG),
|
||||
ASN1_SIMPLE(CMS_CompressedData, compressionAlgorithm, X509_ALGOR),
|
||||
ASN1_SIMPLE(CMS_CompressedData, encapContentInfo, CMS_EncapsulatedContentInfo),
|
||||
} ASN1_NDEF_SEQUENCE_END(CMS_CompressedData)
|
||||
|
||||
/* This is the ANY DEFINED BY table for the top level ContentInfo structure */
|
||||
|
||||
ASN1_ADB_TEMPLATE(cms_default) = ASN1_EXP(CMS_ContentInfo, d.other, ASN1_ANY, 0);
|
||||
|
||||
ASN1_ADB(CMS_ContentInfo) = {
|
||||
ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP(CMS_ContentInfo, d.data, ASN1_OCTET_STRING_NDEF, 0)),
|
||||
ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP(CMS_ContentInfo, d.signedData, CMS_SignedData, 0)),
|
||||
ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP(CMS_ContentInfo, d.envelopedData, CMS_EnvelopedData, 0)),
|
||||
ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP(CMS_ContentInfo, d.digestedData, CMS_DigestedData, 0)),
|
||||
ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP(CMS_ContentInfo, d.encryptedData, CMS_EncryptedData, 0)),
|
||||
ADB_ENTRY(NID_id_smime_ct_authData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authenticatedData, CMS_AuthenticatedData, 0)),
|
||||
ADB_ENTRY(NID_id_smime_ct_compressedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.compressedData, CMS_CompressedData, 0)),
|
||||
} ASN1_ADB_END(CMS_ContentInfo, 0, contentType, 0, &cms_default_tt, NULL);
|
||||
|
||||
/* CMS streaming support */
|
||||
static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
ASN1_STREAM_ARG *sarg = exarg;
|
||||
CMS_ContentInfo *cms = NULL;
|
||||
if (pval)
|
||||
cms = (CMS_ContentInfo *)*pval;
|
||||
else
|
||||
return 1;
|
||||
switch (operation) {
|
||||
|
||||
case ASN1_OP_STREAM_PRE:
|
||||
if (CMS_stream(&sarg->boundary, cms) <= 0)
|
||||
return 0;
|
||||
case ASN1_OP_DETACHED_PRE:
|
||||
sarg->ndef_bio = CMS_dataInit(cms, sarg->out);
|
||||
if (!sarg->ndef_bio)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_OP_STREAM_POST:
|
||||
case ASN1_OP_DETACHED_POST:
|
||||
if (CMS_dataFinal(cms, sarg->ndef_bio) <= 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_NDEF_SEQUENCE_cb(CMS_ContentInfo, cms_cb) = {
|
||||
ASN1_SIMPLE(CMS_ContentInfo, contentType, ASN1_OBJECT),
|
||||
ASN1_ADB_OBJECT(CMS_ContentInfo)
|
||||
} ASN1_NDEF_SEQUENCE_END_cb(CMS_ContentInfo, CMS_ContentInfo)
|
||||
|
||||
/* Specials for signed attributes */
|
||||
|
||||
/*
|
||||
* When signing attributes we want to reorder them to match the sorted
|
||||
* encoding.
|
||||
*/
|
||||
|
||||
ASN1_ITEM_TEMPLATE(CMS_Attributes_Sign) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, CMS_ATTRIBUTES, X509_ATTRIBUTE)
|
||||
ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Sign)
|
||||
|
||||
/*
|
||||
* When verifying attributes we need to use the received order. So we use
|
||||
* SEQUENCE OF and tag it to SET OF
|
||||
*/
|
||||
|
||||
ASN1_ITEM_TEMPLATE(CMS_Attributes_Verify) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL,
|
||||
V_ASN1_SET, CMS_ATTRIBUTES, X509_ATTRIBUTE)
|
||||
ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Verify)
|
||||
|
||||
|
||||
|
||||
ASN1_CHOICE(CMS_ReceiptsFrom) = {
|
||||
ASN1_IMP(CMS_ReceiptsFrom, d.allOrFirstTier, LONG, 0),
|
||||
ASN1_IMP_SEQUENCE_OF(CMS_ReceiptsFrom, d.receiptList, GENERAL_NAMES, 1)
|
||||
} ASN1_CHOICE_END(CMS_ReceiptsFrom)
|
||||
|
||||
ASN1_SEQUENCE(CMS_ReceiptRequest) = {
|
||||
ASN1_SIMPLE(CMS_ReceiptRequest, signedContentIdentifier, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(CMS_ReceiptRequest, receiptsFrom, CMS_ReceiptsFrom),
|
||||
ASN1_SEQUENCE_OF(CMS_ReceiptRequest, receiptsTo, GENERAL_NAMES)
|
||||
} ASN1_SEQUENCE_END(CMS_ReceiptRequest)
|
||||
|
||||
ASN1_SEQUENCE(CMS_Receipt) = {
|
||||
ASN1_SIMPLE(CMS_Receipt, version, LONG),
|
||||
ASN1_SIMPLE(CMS_Receipt, contentType, ASN1_OBJECT),
|
||||
ASN1_SIMPLE(CMS_Receipt, signedContentIdentifier, ASN1_OCTET_STRING),
|
||||
ASN1_SIMPLE(CMS_Receipt, originatorSignatureValue, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END(CMS_Receipt)
|
||||
|
||||
/*
|
||||
* Utilities to encode the CMS_SharedInfo structure used during key
|
||||
* derivation.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
X509_ALGOR *keyInfo;
|
||||
ASN1_OCTET_STRING *entityUInfo;
|
||||
ASN1_OCTET_STRING *suppPubInfo;
|
||||
} CMS_SharedInfo;
|
||||
|
||||
ASN1_SEQUENCE(CMS_SharedInfo) = {
|
||||
ASN1_SIMPLE(CMS_SharedInfo, keyInfo, X509_ALGOR),
|
||||
ASN1_EXP_OPT(CMS_SharedInfo, entityUInfo, ASN1_OCTET_STRING, 0),
|
||||
ASN1_EXP_OPT(CMS_SharedInfo, suppPubInfo, ASN1_OCTET_STRING, 2),
|
||||
} ASN1_SEQUENCE_END(CMS_SharedInfo)
|
||||
|
||||
int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
|
||||
ASN1_OCTET_STRING *ukm, int keylen)
|
||||
{
|
||||
union {
|
||||
CMS_SharedInfo *pecsi;
|
||||
ASN1_VALUE *a;
|
||||
} intsi = {
|
||||
NULL
|
||||
};
|
||||
|
||||
ASN1_OCTET_STRING oklen;
|
||||
unsigned char kl[4];
|
||||
CMS_SharedInfo ecsi;
|
||||
|
||||
keylen <<= 3;
|
||||
kl[0] = (keylen >> 24) & 0xff;
|
||||
kl[1] = (keylen >> 16) & 0xff;
|
||||
kl[2] = (keylen >> 8) & 0xff;
|
||||
kl[3] = keylen & 0xff;
|
||||
oklen.length = 4;
|
||||
oklen.data = kl;
|
||||
oklen.type = V_ASN1_OCTET_STRING;
|
||||
oklen.flags = 0;
|
||||
ecsi.keyInfo = kekalg;
|
||||
ecsi.entityUInfo = ukm;
|
||||
ecsi.suppPubInfo = &oklen;
|
||||
intsi.pecsi = &ecsi;
|
||||
return ASN1_item_i2d(intsi.a, pder, ASN1_ITEM_rptr(CMS_SharedInfo));
|
||||
}
|
197
cms/lib/cms_att.c
Normal file
197
cms/lib/cms_att.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* crypto/cms/cms_att.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
|
||||
/* CMS SignedData Attribute utilities */
|
||||
|
||||
int CMS_signed_get_attr_count(const CMS_SignerInfo *si)
|
||||
{
|
||||
return X509at_get_attr_count(si->signedAttrs);
|
||||
}
|
||||
|
||||
int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, int lastpos)
|
||||
{
|
||||
return X509at_get_attr_by_NID(si->signedAttrs, nid, lastpos);
|
||||
}
|
||||
|
||||
int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
|
||||
int lastpos)
|
||||
{
|
||||
return X509at_get_attr_by_OBJ(si->signedAttrs, obj, lastpos);
|
||||
}
|
||||
|
||||
X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc)
|
||||
{
|
||||
return X509at_get_attr(si->signedAttrs, loc);
|
||||
}
|
||||
|
||||
X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc)
|
||||
{
|
||||
return X509at_delete_attr(si->signedAttrs, loc);
|
||||
}
|
||||
|
||||
int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
|
||||
{
|
||||
if (X509at_add1_attr(&si->signedAttrs, attr))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
|
||||
const ASN1_OBJECT *obj, int type,
|
||||
const void *bytes, int len)
|
||||
{
|
||||
if (X509at_add1_attr_by_OBJ(&si->signedAttrs, obj, type, bytes, len))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
|
||||
int nid, int type, const void *bytes, int len)
|
||||
{
|
||||
if (X509at_add1_attr_by_NID(&si->signedAttrs, nid, type, bytes, len))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
|
||||
const char *attrname, int type,
|
||||
const void *bytes, int len)
|
||||
{
|
||||
if (X509at_add1_attr_by_txt(&si->signedAttrs, attrname, type, bytes, len))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
|
||||
int lastpos, int type)
|
||||
{
|
||||
return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type);
|
||||
}
|
||||
|
||||
int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si)
|
||||
{
|
||||
return X509at_get_attr_count(si->unsignedAttrs);
|
||||
}
|
||||
|
||||
int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
|
||||
int lastpos)
|
||||
{
|
||||
return X509at_get_attr_by_NID(si->unsignedAttrs, nid, lastpos);
|
||||
}
|
||||
|
||||
int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
|
||||
int lastpos)
|
||||
{
|
||||
return X509at_get_attr_by_OBJ(si->unsignedAttrs, obj, lastpos);
|
||||
}
|
||||
|
||||
X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc)
|
||||
{
|
||||
return X509at_get_attr(si->unsignedAttrs, loc);
|
||||
}
|
||||
|
||||
X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc)
|
||||
{
|
||||
return X509at_delete_attr(si->unsignedAttrs, loc);
|
||||
}
|
||||
|
||||
int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
|
||||
{
|
||||
if (X509at_add1_attr(&si->unsignedAttrs, attr))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
|
||||
const ASN1_OBJECT *obj, int type,
|
||||
const void *bytes, int len)
|
||||
{
|
||||
if (X509at_add1_attr_by_OBJ(&si->unsignedAttrs, obj, type, bytes, len))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
|
||||
int nid, int type,
|
||||
const void *bytes, int len)
|
||||
{
|
||||
if (X509at_add1_attr_by_NID(&si->unsignedAttrs, nid, type, bytes, len))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
|
||||
const char *attrname, int type,
|
||||
const void *bytes, int len)
|
||||
{
|
||||
if (X509at_add1_attr_by_txt(&si->unsignedAttrs, attrname,
|
||||
type, bytes, len))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
|
||||
int lastpos, int type)
|
||||
{
|
||||
return X509at_get0_data_by_OBJ(si->unsignedAttrs, oid, lastpos, type);
|
||||
}
|
||||
|
||||
/* Specific attribute cases */
|
134
cms/lib/cms_cd.c
Normal file
134
cms/lib/cms_cd.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* crypto/cms/cms_cd.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include <openssl/bio.h>
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
# include <openssl/comp.h>
|
||||
#endif
|
||||
#include "cms_lcl.h"
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_CompressedData)
|
||||
|
||||
#ifdef ZLIB
|
||||
|
||||
/* CMS CompressedData Utilities */
|
||||
|
||||
CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
CMS_CompressedData *cd;
|
||||
/*
|
||||
* Will need something cleverer if there is ever more than one
|
||||
* compression algorithm or parameters have some meaning...
|
||||
*/
|
||||
if (comp_nid != NID_zlib_compression) {
|
||||
CMSerr(CMS_F_CMS_COMPRESSEDDATA_CREATE,
|
||||
CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
cms = CMS_ContentInfo_new();
|
||||
if (!cms)
|
||||
return NULL;
|
||||
|
||||
cd = M_ASN1_new_of(CMS_CompressedData);
|
||||
|
||||
if (!cd)
|
||||
goto err;
|
||||
|
||||
cms->contentType = OBJ_nid2obj(NID_id_smime_ct_compressedData);
|
||||
cms->d.compressedData = cd;
|
||||
|
||||
cd->version = 0;
|
||||
|
||||
X509_ALGOR_set0(cd->compressionAlgorithm,
|
||||
OBJ_nid2obj(NID_zlib_compression), V_ASN1_UNDEF, NULL);
|
||||
|
||||
cd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data);
|
||||
|
||||
return cms;
|
||||
|
||||
err:
|
||||
|
||||
if (cms)
|
||||
CMS_ContentInfo_free(cms);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms)
|
||||
{
|
||||
CMS_CompressedData *cd;
|
||||
ASN1_OBJECT *compoid;
|
||||
if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_compressedData) {
|
||||
CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO,
|
||||
CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA);
|
||||
return NULL;
|
||||
}
|
||||
cd = cms->d.compressedData;
|
||||
X509_ALGOR_get0(&compoid, NULL, NULL, cd->compressionAlgorithm);
|
||||
if (OBJ_obj2nid(compoid) != NID_zlib_compression) {
|
||||
CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO,
|
||||
CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
return BIO_new(BIO_f_zlib());
|
||||
}
|
||||
|
||||
#endif
|
145
cms/lib/cms_dd.c
Normal file
145
cms/lib/cms_dd.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/* crypto/cms/cms_dd.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_DigestedData)
|
||||
|
||||
/* CMS DigestedData Utilities */
|
||||
|
||||
CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
CMS_DigestedData *dd;
|
||||
cms = CMS_ContentInfo_new();
|
||||
if (!cms)
|
||||
return NULL;
|
||||
|
||||
dd = M_ASN1_new_of(CMS_DigestedData);
|
||||
|
||||
if (!dd)
|
||||
goto err;
|
||||
|
||||
cms->contentType = OBJ_nid2obj(NID_pkcs7_digest);
|
||||
cms->d.digestedData = dd;
|
||||
|
||||
dd->version = 0;
|
||||
dd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data);
|
||||
|
||||
cms_DigestAlgorithm_set(dd->digestAlgorithm, md);
|
||||
|
||||
return cms;
|
||||
|
||||
err:
|
||||
|
||||
if (cms)
|
||||
CMS_ContentInfo_free(cms);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms)
|
||||
{
|
||||
CMS_DigestedData *dd;
|
||||
dd = cms->d.digestedData;
|
||||
return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm);
|
||||
}
|
||||
|
||||
int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify)
|
||||
{
|
||||
EVP_MD_CTX mctx;
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
unsigned int mdlen;
|
||||
int r = 0;
|
||||
CMS_DigestedData *dd;
|
||||
EVP_MD_CTX_init(&mctx);
|
||||
|
||||
dd = cms->d.digestedData;
|
||||
|
||||
if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, dd->digestAlgorithm))
|
||||
goto err;
|
||||
|
||||
if (EVP_DigestFinal_ex(&mctx, md, &mdlen) <= 0)
|
||||
goto err;
|
||||
|
||||
if (verify) {
|
||||
if (mdlen != (unsigned int)dd->digest->length) {
|
||||
CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL,
|
||||
CMS_R_MESSAGEDIGEST_WRONG_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(md, dd->digest->data, mdlen))
|
||||
CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL,
|
||||
CMS_R_VERIFICATION_FAILURE);
|
||||
else
|
||||
r = 1;
|
||||
} else {
|
||||
if (!ASN1_STRING_set(dd->digest, md, mdlen))
|
||||
goto err;
|
||||
r = 1;
|
||||
}
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_cleanup(&mctx);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
264
cms/lib/cms_enc.c
Normal file
264
cms/lib/cms_enc.c
Normal file
|
@ -0,0 +1,264 @@
|
|||
/* crypto/cms/cms_enc.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include <openssl/rand.h>
|
||||
#include "cms_lcl.h"
|
||||
|
||||
/* CMS EncryptedData Utilities */
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_EncryptedData)
|
||||
|
||||
/* Return BIO based on EncryptedContentInfo and key */
|
||||
|
||||
BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
|
||||
{
|
||||
BIO *b;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
const EVP_CIPHER *ciph;
|
||||
X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
|
||||
unsigned char *tkey = NULL;
|
||||
size_t tkeylen = 0;
|
||||
|
||||
int ok = 0;
|
||||
|
||||
int enc, keep_key = 0;
|
||||
|
||||
enc = ec->cipher ? 1 : 0;
|
||||
|
||||
b = BIO_new(BIO_f_cipher());
|
||||
if (!b) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO_get_cipher_ctx(b, &ctx);
|
||||
|
||||
if (enc) {
|
||||
ciph = ec->cipher;
|
||||
/*
|
||||
* If not keeping key set cipher to NULL so subsequent calls decrypt.
|
||||
*/
|
||||
if (ec->key)
|
||||
ec->cipher = NULL;
|
||||
} else {
|
||||
ciph = EVP_get_cipherbyobj(calg->algorithm);
|
||||
|
||||
if (!ciph) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
|
||||
CMS_R_CIPHER_INITIALISATION_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (enc) {
|
||||
int ivlen;
|
||||
calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
|
||||
/* Generate a random IV if we need one */
|
||||
ivlen = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
if (ivlen > 0) {
|
||||
if (RAND_bytes(iv, ivlen) <= 0)
|
||||
goto err;
|
||||
piv = iv;
|
||||
}
|
||||
} else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
|
||||
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
|
||||
goto err;
|
||||
}
|
||||
tkeylen = EVP_CIPHER_CTX_key_length(ctx);
|
||||
/* Generate random session key */
|
||||
if (!enc || !ec->key) {
|
||||
tkey = OPENSSL_malloc(tkeylen);
|
||||
if (!tkey) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ec->key) {
|
||||
ec->key = tkey;
|
||||
ec->keylen = tkeylen;
|
||||
tkey = NULL;
|
||||
if (enc)
|
||||
keep_key = 1;
|
||||
else
|
||||
ERR_clear_error();
|
||||
|
||||
}
|
||||
|
||||
if (ec->keylen != tkeylen) {
|
||||
/* If necessary set key length */
|
||||
if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) {
|
||||
/*
|
||||
* Only reveal failure if debugging so we don't leak information
|
||||
* which may be useful in MMA.
|
||||
*/
|
||||
if (enc || ec->debug) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
|
||||
CMS_R_INVALID_KEY_LENGTH);
|
||||
goto err;
|
||||
} else {
|
||||
/* Use random key */
|
||||
OPENSSL_cleanse(ec->key, ec->keylen);
|
||||
OPENSSL_free(ec->key);
|
||||
ec->key = tkey;
|
||||
ec->keylen = tkeylen;
|
||||
tkey = NULL;
|
||||
ERR_clear_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
|
||||
CMS_R_CIPHER_INITIALISATION_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (enc) {
|
||||
calg->parameter = ASN1_TYPE_new();
|
||||
if (calg->parameter == NULL) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
|
||||
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
|
||||
goto err;
|
||||
}
|
||||
/* If parameter type not set omit parameter */
|
||||
if (calg->parameter->type == V_ASN1_UNDEF) {
|
||||
ASN1_TYPE_free(calg->parameter);
|
||||
calg->parameter = NULL;
|
||||
}
|
||||
}
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
if (ec->key && (!keep_key || !ok)) {
|
||||
OPENSSL_cleanse(ec->key, ec->keylen);
|
||||
OPENSSL_free(ec->key);
|
||||
ec->key = NULL;
|
||||
}
|
||||
if (tkey) {
|
||||
OPENSSL_cleanse(tkey, tkeylen);
|
||||
OPENSSL_free(tkey);
|
||||
}
|
||||
if (ok)
|
||||
return b;
|
||||
BIO_free(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
|
||||
const EVP_CIPHER *cipher,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
ec->cipher = cipher;
|
||||
if (key) {
|
||||
ec->key = OPENSSL_malloc(keylen);
|
||||
if (!ec->key)
|
||||
return 0;
|
||||
memcpy(ec->key, key, keylen);
|
||||
}
|
||||
ec->keylen = keylen;
|
||||
if (cipher)
|
||||
ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
if (!key || !keylen) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
|
||||
return 0;
|
||||
}
|
||||
if (ciph) {
|
||||
cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
|
||||
if (!cms->d.encryptedData) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
|
||||
cms->d.encryptedData->version = 0;
|
||||
} else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA);
|
||||
return 0;
|
||||
}
|
||||
ec = cms->d.encryptedData->encryptedContentInfo;
|
||||
return cms_EncryptedContent_init(ec, ciph, key, keylen);
|
||||
}
|
||||
|
||||
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
|
||||
{
|
||||
CMS_EncryptedData *enc = cms->d.encryptedData;
|
||||
if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
|
||||
enc->version = 2;
|
||||
return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
|
||||
}
|
977
cms/lib/cms_env.c
Normal file
977
cms/lib/cms_env.c
Normal file
|
@ -0,0 +1,977 @@
|
|||
/* crypto/cms/cms_env.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/aes.h>
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
extern int libressl_pkey_ctrl(EVP_PKEY *, int, long, void *);
|
||||
extern int libressl_pkey_ctx_ctrl(EVP_PKEY_CTX *, int, int, int, int, void *);
|
||||
|
||||
/* CMS EnvelopedData Utilities */
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_EnvelopedData)
|
||||
DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
|
||||
|
||||
DECLARE_STACK_OF(CMS_RecipientInfo)
|
||||
|
||||
CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
|
||||
{
|
||||
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
|
||||
CMSerr(CMS_F_CMS_GET0_ENVELOPED,
|
||||
CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
|
||||
return NULL;
|
||||
}
|
||||
return cms->d.envelopedData;
|
||||
}
|
||||
|
||||
static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
|
||||
{
|
||||
if (cms->d.other == NULL) {
|
||||
cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);
|
||||
if (!cms->d.envelopedData) {
|
||||
CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
cms->d.envelopedData->version = 0;
|
||||
cms->d.envelopedData->encryptedContentInfo->contentType =
|
||||
OBJ_nid2obj(NID_pkcs7_data);
|
||||
ASN1_OBJECT_free(cms->contentType);
|
||||
cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
|
||||
return cms->d.envelopedData;
|
||||
}
|
||||
return cms_get0_enveloped(cms);
|
||||
}
|
||||
|
||||
int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
int i;
|
||||
if (ri->type == CMS_RECIPINFO_TRANS)
|
||||
pkey = ri->d.ktri->pkey;
|
||||
else if (ri->type == CMS_RECIPINFO_AGREE) {
|
||||
EVP_PKEY_CTX *pctx = ri->d.kari->pctx;
|
||||
if (!pctx)
|
||||
return 0;
|
||||
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
|
||||
if (!pkey)
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
|
||||
return 1;
|
||||
i = libressl_pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
|
||||
if (i == -2) {
|
||||
CMSerr(CMS_F_CMS_ENV_ASN1_CTRL,
|
||||
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
return 0;
|
||||
}
|
||||
if (i <= 0) {
|
||||
CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_CTRL_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
|
||||
{
|
||||
CMS_EnvelopedData *env;
|
||||
env = cms_get0_enveloped(cms);
|
||||
if (!env)
|
||||
return NULL;
|
||||
return env->recipientInfos;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
|
||||
{
|
||||
return ri->type;
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
|
||||
{
|
||||
if (ri->type == CMS_RECIPINFO_TRANS)
|
||||
return ri->d.ktri->pctx;
|
||||
else if (ri->type == CMS_RECIPINFO_AGREE)
|
||||
return ri->d.kari->pctx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
CMS_EnvelopedData *env;
|
||||
cms = CMS_ContentInfo_new();
|
||||
if (!cms)
|
||||
goto merr;
|
||||
env = cms_enveloped_data_init(cms);
|
||||
if (!env)
|
||||
goto merr;
|
||||
if (!cms_EncryptedContent_init(env->encryptedContentInfo,
|
||||
cipher, NULL, 0))
|
||||
goto merr;
|
||||
return cms;
|
||||
merr:
|
||||
if (cms)
|
||||
CMS_ContentInfo_free(cms);
|
||||
CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Key Transport Recipient Info (KTRI) routines */
|
||||
|
||||
/* Initialise a ktri based on passed certificate and key */
|
||||
|
||||
static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
|
||||
EVP_PKEY *pk, unsigned int flags)
|
||||
{
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
int idtype;
|
||||
|
||||
ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
|
||||
if (!ri->d.ktri)
|
||||
return 0;
|
||||
ri->type = CMS_RECIPINFO_TRANS;
|
||||
|
||||
ktri = ri->d.ktri;
|
||||
|
||||
if (flags & CMS_USE_KEYID) {
|
||||
ktri->version = 2;
|
||||
idtype = CMS_RECIPINFO_KEYIDENTIFIER;
|
||||
} else {
|
||||
ktri->version = 0;
|
||||
idtype = CMS_RECIPINFO_ISSUER_SERIAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not a typo: RecipientIdentifier and SignerIdentifier are the same
|
||||
* structure.
|
||||
*/
|
||||
|
||||
if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype))
|
||||
return 0;
|
||||
|
||||
CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
|
||||
CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
|
||||
ktri->pkey = pk;
|
||||
ktri->recip = recip;
|
||||
|
||||
if (flags & CMS_KEY_PARAM) {
|
||||
ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
|
||||
if (!ktri->pctx)
|
||||
return 0;
|
||||
if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
|
||||
return 0;
|
||||
} else if (!cms_env_asn1_ctrl(ri, 0))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a recipient certificate using appropriate type of RecipientInfo
|
||||
*/
|
||||
|
||||
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
|
||||
X509 *recip, unsigned int flags)
|
||||
{
|
||||
CMS_RecipientInfo *ri = NULL;
|
||||
CMS_EnvelopedData *env;
|
||||
EVP_PKEY *pk = NULL;
|
||||
env = cms_get0_enveloped(cms);
|
||||
if (!env)
|
||||
goto err;
|
||||
|
||||
/* Initialize recipient info */
|
||||
ri = M_ASN1_new_of(CMS_RecipientInfo);
|
||||
if (!ri)
|
||||
goto merr;
|
||||
|
||||
pk = X509_get_pubkey(recip);
|
||||
if (!pk) {
|
||||
CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (cms_pkey_get_ri_type(pk)) {
|
||||
|
||||
case CMS_RECIPINFO_TRANS:
|
||||
if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags))
|
||||
goto err;
|
||||
break;
|
||||
|
||||
case CMS_RECIPINFO_AGREE:
|
||||
if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags))
|
||||
goto err;
|
||||
break;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
|
||||
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
goto err;
|
||||
|
||||
}
|
||||
|
||||
if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
|
||||
goto merr;
|
||||
|
||||
EVP_PKEY_free(pk);
|
||||
|
||||
return ri;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
if (ri)
|
||||
M_ASN1_free_of(ri, CMS_RecipientInfo);
|
||||
if (pk)
|
||||
EVP_PKEY_free(pk);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
|
||||
EVP_PKEY **pk, X509 **recip,
|
||||
X509_ALGOR **palg)
|
||||
{
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
if (ri->type != CMS_RECIPINFO_TRANS) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,
|
||||
CMS_R_NOT_KEY_TRANSPORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ktri = ri->d.ktri;
|
||||
|
||||
if (pk)
|
||||
*pk = ktri->pkey;
|
||||
if (recip)
|
||||
*recip = ktri->recip;
|
||||
if (palg)
|
||||
*palg = ktri->keyEncryptionAlgorithm;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer,
|
||||
ASN1_INTEGER **sno)
|
||||
{
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
if (ri->type != CMS_RECIPINFO_TRANS) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,
|
||||
CMS_R_NOT_KEY_TRANSPORT);
|
||||
return 0;
|
||||
}
|
||||
ktri = ri->d.ktri;
|
||||
|
||||
return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno);
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
|
||||
{
|
||||
if (ri->type != CMS_RECIPINFO_TRANS) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
|
||||
CMS_R_NOT_KEY_TRANSPORT);
|
||||
return -2;
|
||||
}
|
||||
return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
|
||||
{
|
||||
if (ri->type != CMS_RECIPINFO_TRANS) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, CMS_R_NOT_KEY_TRANSPORT);
|
||||
return 0;
|
||||
}
|
||||
ri->d.ktri->pkey = pkey;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Encrypt content key in key transport recipient info */
|
||||
|
||||
static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri)
|
||||
{
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
unsigned char *ek = NULL;
|
||||
size_t eklen;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (ri->type != CMS_RECIPINFO_TRANS) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_NOT_KEY_TRANSPORT);
|
||||
return 0;
|
||||
}
|
||||
ktri = ri->d.ktri;
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
|
||||
pctx = ktri->pctx;
|
||||
|
||||
if (pctx) {
|
||||
if (!cms_env_asn1_ctrl(ri, 0))
|
||||
goto err;
|
||||
} else {
|
||||
pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
|
||||
if (!pctx)
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_encrypt_init(pctx) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (libressl_pkey_ctx_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
|
||||
EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
|
||||
goto err;
|
||||
|
||||
ek = OPENSSL_malloc(eklen);
|
||||
|
||||
if (ek == NULL) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
|
||||
goto err;
|
||||
|
||||
ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
|
||||
ek = NULL;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (pctx) {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
ktri->pctx = NULL;
|
||||
}
|
||||
if (ek)
|
||||
OPENSSL_free(ek);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* Decrypt content key from KTRI */
|
||||
|
||||
static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri)
|
||||
{
|
||||
CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
|
||||
EVP_PKEY *pkey = ktri->pkey;
|
||||
unsigned char *ek = NULL;
|
||||
size_t eklen;
|
||||
int ret = 0;
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
|
||||
if (ktri->pkey == NULL) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (!ktri->pctx)
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
|
||||
goto err;
|
||||
|
||||
if (!cms_env_asn1_ctrl(ri, 1))
|
||||
goto err;
|
||||
|
||||
if (libressl_pkey_ctx_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT,
|
||||
EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
|
||||
ktri->encryptedKey->data,
|
||||
ktri->encryptedKey->length) <= 0)
|
||||
goto err;
|
||||
|
||||
ek = OPENSSL_malloc(eklen);
|
||||
|
||||
if (ek == NULL) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
|
||||
ktri->encryptedKey->data,
|
||||
ktri->encryptedKey->length) <= 0) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
if (ec->key) {
|
||||
OPENSSL_cleanse(ec->key, ec->keylen);
|
||||
OPENSSL_free(ec->key);
|
||||
}
|
||||
|
||||
ec->key = ek;
|
||||
ec->keylen = eklen;
|
||||
|
||||
err:
|
||||
if (ktri->pctx) {
|
||||
EVP_PKEY_CTX_free(ktri->pctx);
|
||||
ktri->pctx = NULL;
|
||||
}
|
||||
if (!ret && ek)
|
||||
OPENSSL_free(ek);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Key Encrypted Key (KEK) RecipientInfo routines */
|
||||
|
||||
int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
|
||||
const unsigned char *id, size_t idlen)
|
||||
{
|
||||
ASN1_OCTET_STRING tmp_os;
|
||||
CMS_KEKRecipientInfo *kekri;
|
||||
if (ri->type != CMS_RECIPINFO_KEK) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
|
||||
return -2;
|
||||
}
|
||||
kekri = ri->d.kekri;
|
||||
tmp_os.type = V_ASN1_OCTET_STRING;
|
||||
tmp_os.flags = 0;
|
||||
tmp_os.data = (unsigned char *)id;
|
||||
tmp_os.length = (int)idlen;
|
||||
return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
|
||||
}
|
||||
|
||||
/* For now hard code AES key wrap info */
|
||||
|
||||
static size_t aes_wrap_keylen(int nid)
|
||||
{
|
||||
switch (nid) {
|
||||
case NID_id_aes128_wrap:
|
||||
return 16;
|
||||
|
||||
case NID_id_aes192_wrap:
|
||||
return 24;
|
||||
|
||||
case NID_id_aes256_wrap:
|
||||
return 32;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
|
||||
unsigned char *key, size_t keylen,
|
||||
unsigned char *id, size_t idlen,
|
||||
ASN1_GENERALIZEDTIME *date,
|
||||
ASN1_OBJECT *otherTypeId,
|
||||
ASN1_TYPE *otherType)
|
||||
{
|
||||
CMS_RecipientInfo *ri = NULL;
|
||||
CMS_EnvelopedData *env;
|
||||
CMS_KEKRecipientInfo *kekri;
|
||||
env = cms_get0_enveloped(cms);
|
||||
if (!env)
|
||||
goto err;
|
||||
|
||||
if (nid == NID_undef) {
|
||||
switch (keylen) {
|
||||
case 16:
|
||||
nid = NID_id_aes128_wrap;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
nid = NID_id_aes192_wrap;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
nid = NID_id_aes256_wrap;
|
||||
break;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
size_t exp_keylen = aes_wrap_keylen(nid);
|
||||
|
||||
if (!exp_keylen) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
|
||||
CMS_R_UNSUPPORTED_KEK_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (keylen != exp_keylen) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Initialize recipient info */
|
||||
ri = M_ASN1_new_of(CMS_RecipientInfo);
|
||||
if (!ri)
|
||||
goto merr;
|
||||
|
||||
ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
|
||||
if (!ri->d.kekri)
|
||||
goto merr;
|
||||
ri->type = CMS_RECIPINFO_KEK;
|
||||
|
||||
kekri = ri->d.kekri;
|
||||
|
||||
if (otherTypeId) {
|
||||
kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
|
||||
if (kekri->kekid->other == NULL)
|
||||
goto merr;
|
||||
}
|
||||
|
||||
if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
|
||||
goto merr;
|
||||
|
||||
/* After this point no calls can fail */
|
||||
|
||||
kekri->version = 4;
|
||||
|
||||
kekri->key = key;
|
||||
kekri->keylen = keylen;
|
||||
|
||||
ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
|
||||
|
||||
kekri->kekid->date = date;
|
||||
|
||||
if (kekri->kekid->other) {
|
||||
kekri->kekid->other->keyAttrId = otherTypeId;
|
||||
kekri->kekid->other->keyAttr = otherType;
|
||||
}
|
||||
|
||||
X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
|
||||
OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
|
||||
|
||||
return ri;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
if (ri)
|
||||
M_ASN1_free_of(ri, CMS_RecipientInfo);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
|
||||
X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pid,
|
||||
ASN1_GENERALIZEDTIME **pdate,
|
||||
ASN1_OBJECT **potherid,
|
||||
ASN1_TYPE **pothertype)
|
||||
{
|
||||
CMS_KEKIdentifier *rkid;
|
||||
if (ri->type != CMS_RECIPINFO_KEK) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);
|
||||
return 0;
|
||||
}
|
||||
rkid = ri->d.kekri->kekid;
|
||||
if (palg)
|
||||
*palg = ri->d.kekri->keyEncryptionAlgorithm;
|
||||
if (pid)
|
||||
*pid = rkid->keyIdentifier;
|
||||
if (pdate)
|
||||
*pdate = rkid->date;
|
||||
if (potherid) {
|
||||
if (rkid->other)
|
||||
*potherid = rkid->other->keyAttrId;
|
||||
else
|
||||
*potherid = NULL;
|
||||
}
|
||||
if (pothertype) {
|
||||
if (rkid->other)
|
||||
*pothertype = rkid->other->keyAttr;
|
||||
else
|
||||
*pothertype = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
|
||||
unsigned char *key, size_t keylen)
|
||||
{
|
||||
CMS_KEKRecipientInfo *kekri;
|
||||
if (ri->type != CMS_RECIPINFO_KEK) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kekri = ri->d.kekri;
|
||||
kekri->key = key;
|
||||
kekri->keylen = keylen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Encrypt content key in KEK recipient info */
|
||||
|
||||
static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri)
|
||||
{
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
CMS_KEKRecipientInfo *kekri;
|
||||
AES_KEY actx;
|
||||
unsigned char *wkey = NULL;
|
||||
int wkeylen;
|
||||
int r = 0;
|
||||
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
|
||||
kekri = ri->d.kekri;
|
||||
|
||||
if (!kekri->key) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
|
||||
CMS_R_ERROR_SETTING_KEY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
wkey = OPENSSL_malloc(ec->keylen + 8);
|
||||
|
||||
if (!wkey) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);
|
||||
|
||||
if (wkeylen <= 0) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (!r && wkey)
|
||||
OPENSSL_free(wkey);
|
||||
OPENSSL_cleanse(&actx, sizeof(actx));
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
/* Decrypt content key in KEK recipient info */
|
||||
|
||||
static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri)
|
||||
{
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
CMS_KEKRecipientInfo *kekri;
|
||||
AES_KEY actx;
|
||||
unsigned char *ukey = NULL;
|
||||
int ukeylen;
|
||||
int r = 0, wrap_nid;
|
||||
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
|
||||
kekri = ri->d.kekri;
|
||||
|
||||
if (!kekri->key) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
|
||||
if (aes_wrap_keylen(wrap_nid) != kekri->keylen) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
|
||||
CMS_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If encrypted key length is invalid don't bother */
|
||||
|
||||
if (kekri->encryptedKey->length < 16) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
|
||||
CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
|
||||
CMS_R_ERROR_SETTING_KEY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);
|
||||
|
||||
if (!ukey) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ukeylen = AES_unwrap_key(&actx, NULL, ukey,
|
||||
kekri->encryptedKey->data,
|
||||
kekri->encryptedKey->length);
|
||||
|
||||
if (ukeylen <= 0) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_UNWRAP_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ec->key = ukey;
|
||||
ec->keylen = ukeylen;
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (!r && ukey)
|
||||
OPENSSL_free(ukey);
|
||||
OPENSSL_cleanse(&actx, sizeof(actx));
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
|
||||
{
|
||||
switch (ri->type) {
|
||||
case CMS_RECIPINFO_TRANS:
|
||||
return cms_RecipientInfo_ktri_decrypt(cms, ri);
|
||||
|
||||
case CMS_RECIPINFO_KEK:
|
||||
return cms_RecipientInfo_kekri_decrypt(cms, ri);
|
||||
|
||||
case CMS_RECIPINFO_PASS:
|
||||
return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
|
||||
CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
|
||||
{
|
||||
switch (ri->type) {
|
||||
case CMS_RECIPINFO_TRANS:
|
||||
return cms_RecipientInfo_ktri_encrypt(cms, ri);
|
||||
|
||||
case CMS_RECIPINFO_AGREE:
|
||||
return cms_RecipientInfo_kari_encrypt(cms, ri);
|
||||
|
||||
case CMS_RECIPINFO_KEK:
|
||||
return cms_RecipientInfo_kekri_encrypt(cms, ri);
|
||||
break;
|
||||
|
||||
case CMS_RECIPINFO_PASS:
|
||||
return cms_RecipientInfo_pwri_crypt(cms, ri, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_ENCRYPT,
|
||||
CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check structures and fixup version numbers (if necessary) */
|
||||
|
||||
static void cms_env_set_originfo_version(CMS_EnvelopedData *env)
|
||||
{
|
||||
CMS_OriginatorInfo *org = env->originatorInfo;
|
||||
int i;
|
||||
if (org == NULL)
|
||||
return;
|
||||
for (i = 0; i < sk_CMS_CertificateChoices_num(org->certificates); i++) {
|
||||
CMS_CertificateChoices *cch;
|
||||
cch = sk_CMS_CertificateChoices_value(org->certificates, i);
|
||||
if (cch->type == CMS_CERTCHOICE_OTHER) {
|
||||
env->version = 4;
|
||||
return;
|
||||
} else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
|
||||
if (env->version < 3)
|
||||
env->version = 3;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sk_CMS_RevocationInfoChoice_num(org->crls); i++) {
|
||||
CMS_RevocationInfoChoice *rch;
|
||||
rch = sk_CMS_RevocationInfoChoice_value(org->crls, i);
|
||||
if (rch->type == CMS_REVCHOICE_OTHER) {
|
||||
env->version = 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cms_env_set_version(CMS_EnvelopedData *env)
|
||||
{
|
||||
int i;
|
||||
CMS_RecipientInfo *ri;
|
||||
|
||||
/*
|
||||
* Can't set version higher than 4 so if 4 or more already nothing to do.
|
||||
*/
|
||||
if (env->version >= 4)
|
||||
return;
|
||||
|
||||
cms_env_set_originfo_version(env);
|
||||
|
||||
if (env->version >= 3)
|
||||
return;
|
||||
|
||||
for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++) {
|
||||
ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i);
|
||||
if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER) {
|
||||
env->version = 3;
|
||||
return;
|
||||
} else if (ri->type != CMS_RECIPINFO_TRANS
|
||||
|| ri->d.ktri->version != 0) {
|
||||
env->version = 2;
|
||||
}
|
||||
}
|
||||
if (env->version == 2)
|
||||
return;
|
||||
if (env->originatorInfo || env->unprotectedAttrs)
|
||||
env->version = 2;
|
||||
env->version = 0;
|
||||
}
|
||||
|
||||
BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
|
||||
{
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
STACK_OF(CMS_RecipientInfo) *rinfos;
|
||||
CMS_RecipientInfo *ri;
|
||||
int i, ok = 0;
|
||||
BIO *ret;
|
||||
|
||||
/* Get BIO first to set up key */
|
||||
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
ret = cms_EncryptedContent_init_bio(ec);
|
||||
|
||||
/* If error or no cipher end of processing */
|
||||
|
||||
if (!ret || !ec->cipher)
|
||||
return ret;
|
||||
|
||||
/* Now encrypt content key according to each RecipientInfo type */
|
||||
|
||||
rinfos = cms->d.envelopedData->recipientInfos;
|
||||
|
||||
for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
|
||||
ri = sk_CMS_RecipientInfo_value(rinfos, i);
|
||||
if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
|
||||
CMS_R_ERROR_SETTING_RECIPIENTINFO);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
cms_env_set_version(cms->d.envelopedData);
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
ec->cipher = NULL;
|
||||
if (ec->key) {
|
||||
OPENSSL_cleanse(ec->key, ec->keylen);
|
||||
OPENSSL_free(ec->key);
|
||||
ec->key = NULL;
|
||||
ec->keylen = 0;
|
||||
}
|
||||
if (ok)
|
||||
return ret;
|
||||
BIO_free(ret);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Get RecipientInfo type (if any) supported by a key (public or private). To
|
||||
* retain compatibility with previous behaviour if the ctrl value isn't
|
||||
* supported we assume key transport.
|
||||
*/
|
||||
int cms_pkey_get_ri_type(EVP_PKEY *pk)
|
||||
{
|
||||
if (pk->ameth && pk->ameth->pkey_ctrl) {
|
||||
int i, r;
|
||||
i = libressl_pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r);
|
||||
if (i > 0)
|
||||
return r;
|
||||
}
|
||||
return CMS_RECIPINFO_TRANS;
|
||||
}
|
309
cms/lib/cms_err.c
Normal file
309
cms/lib/cms_err.c
Normal file
|
@ -0,0 +1,309 @@
|
|||
/* crypto/cms/cms_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2013 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: this file was auto generated by the mkerr.pl script: any changes
|
||||
* made to it will be overwritten when the script next updates this file,
|
||||
* only reason strings will be preserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
# define ERR_FUNC(func) ERR_PACK(ERR_LIB_CMS,func,0)
|
||||
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_CMS,0,reason)
|
||||
|
||||
static ERR_STRING_DATA CMS_str_functs[] = {
|
||||
{ERR_FUNC(CMS_F_CHECK_CONTENT), "CHECK_CONTENT"},
|
||||
{ERR_FUNC(CMS_F_CMS_ADD0_CERT), "CMS_add0_cert"},
|
||||
{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY), "CMS_add0_recipient_key"},
|
||||
{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD),
|
||||
"CMS_add0_recipient_password"},
|
||||
{ERR_FUNC(CMS_F_CMS_ADD1_RECEIPTREQUEST), "CMS_add1_ReceiptRequest"},
|
||||
{ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT), "CMS_add1_recipient_cert"},
|
||||
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNER), "CMS_add1_signer"},
|
||||
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME), "CMS_ADD1_SIGNINGTIME"},
|
||||
{ERR_FUNC(CMS_F_CMS_COMPRESS), "CMS_compress"},
|
||||
{ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_CREATE), "cms_CompressedData_create"},
|
||||
{ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO),
|
||||
"cms_CompressedData_init_bio"},
|
||||
{ERR_FUNC(CMS_F_CMS_COPY_CONTENT), "CMS_COPY_CONTENT"},
|
||||
{ERR_FUNC(CMS_F_CMS_COPY_MESSAGEDIGEST), "CMS_COPY_MESSAGEDIGEST"},
|
||||
{ERR_FUNC(CMS_F_CMS_DATA), "CMS_data"},
|
||||
{ERR_FUNC(CMS_F_CMS_DATAFINAL), "CMS_dataFinal"},
|
||||
{ERR_FUNC(CMS_F_CMS_DATAINIT), "CMS_dataInit"},
|
||||
{ERR_FUNC(CMS_F_CMS_DECRYPT), "CMS_decrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_KEY), "CMS_decrypt_set1_key"},
|
||||
{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PASSWORD), "CMS_decrypt_set1_password"},
|
||||
{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PKEY), "CMS_decrypt_set1_pkey"},
|
||||
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX),
|
||||
"cms_DigestAlgorithm_find_ctx"},
|
||||
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO),
|
||||
"cms_DigestAlgorithm_init_bio"},
|
||||
{ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL), "cms_DigestedData_do_final"},
|
||||
{ERR_FUNC(CMS_F_CMS_DIGEST_VERIFY), "CMS_digest_verify"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCODE_RECEIPT), "cms_encode_Receipt"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPT), "CMS_encrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO),
|
||||
"cms_EncryptedContent_init_bio"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT), "CMS_EncryptedData_decrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT), "CMS_EncryptedData_encrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY),
|
||||
"CMS_EncryptedData_set1_key"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_CREATE), "CMS_EnvelopedData_create"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO),
|
||||
"cms_EnvelopedData_init_bio"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENVELOPED_DATA_INIT), "CMS_ENVELOPED_DATA_INIT"},
|
||||
{ERR_FUNC(CMS_F_CMS_ENV_ASN1_CTRL), "cms_env_asn1_ctrl"},
|
||||
{ERR_FUNC(CMS_F_CMS_FINAL), "CMS_final"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES),
|
||||
"CMS_GET0_CERTIFICATE_CHOICES"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_CONTENT), "CMS_get0_content"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_ECONTENT_TYPE), "CMS_GET0_ECONTENT_TYPE"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED), "cms_get0_enveloped"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES),
|
||||
"CMS_GET0_REVOCATION_CHOICES"},
|
||||
{ERR_FUNC(CMS_F_CMS_GET0_SIGNED), "CMS_GET0_SIGNED"},
|
||||
{ERR_FUNC(CMS_F_CMS_MSGSIGDIGEST_ADD1), "cms_msgSigDigest_add1"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECEIPTREQUEST_CREATE0),
|
||||
"CMS_ReceiptRequest_create0"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECEIPT_VERIFY), "cms_Receipt_verify"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT), "CMS_RecipientInfo_decrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_ENCRYPT), "CMS_RecipientInfo_encrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT),
|
||||
"cms_RecipientInfo_kari_encrypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG),
|
||||
"CMS_RecipientInfo_kari_get0_alg"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID),
|
||||
"CMS_RecipientInfo_kari_get0_orig_id"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS),
|
||||
"CMS_RecipientInfo_kari_get0_reks"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP),
|
||||
"CMS_RecipientInfo_kari_orig_id_cmp"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT),
|
||||
"CMS_RECIPIENTINFO_KEKRI_DECRYPT"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT),
|
||||
"CMS_RECIPIENTINFO_KEKRI_ENCRYPT"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID),
|
||||
"CMS_RecipientInfo_kekri_get0_id"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP),
|
||||
"CMS_RecipientInfo_kekri_id_cmp"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP),
|
||||
"CMS_RecipientInfo_ktri_cert_cmp"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT),
|
||||
"CMS_RECIPIENTINFO_KTRI_DECRYPT"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT),
|
||||
"CMS_RECIPIENTINFO_KTRI_ENCRYPT"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS),
|
||||
"CMS_RecipientInfo_ktri_get0_algs"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID),
|
||||
"CMS_RecipientInfo_ktri_get0_signer_id"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT),
|
||||
"cms_RecipientInfo_pwri_crypt"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY),
|
||||
"CMS_RecipientInfo_set0_key"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD),
|
||||
"CMS_RecipientInfo_set0_password"},
|
||||
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY),
|
||||
"CMS_RecipientInfo_set0_pkey"},
|
||||
{ERR_FUNC(CMS_F_CMS_SD_ASN1_CTRL), "CMS_SD_ASN1_CTRL"},
|
||||
{ERR_FUNC(CMS_F_CMS_SET1_IAS), "cms_set1_ias"},
|
||||
{ERR_FUNC(CMS_F_CMS_SET1_KEYID), "cms_set1_keyid"},
|
||||
{ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER), "cms_set1_SignerIdentifier"},
|
||||
{ERR_FUNC(CMS_F_CMS_SET_DETACHED), "CMS_set_detached"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGN), "CMS_sign"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNED_DATA_INIT), "CMS_SIGNED_DATA_INIT"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN),
|
||||
"CMS_SIGNERINFO_CONTENT_SIGN"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_SIGN), "CMS_SignerInfo_sign"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY), "CMS_SignerInfo_verify"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CERT),
|
||||
"CMS_SIGNERINFO_VERIFY_CERT"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT),
|
||||
"CMS_SignerInfo_verify_content"},
|
||||
{ERR_FUNC(CMS_F_CMS_SIGN_RECEIPT), "CMS_sign_receipt"},
|
||||
{ERR_FUNC(CMS_F_CMS_STREAM), "CMS_stream"},
|
||||
{ERR_FUNC(CMS_F_CMS_UNCOMPRESS), "CMS_uncompress"},
|
||||
{ERR_FUNC(CMS_F_CMS_VERIFY), "CMS_verify"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA CMS_str_reasons[] = {
|
||||
{ERR_REASON(CMS_R_ADD_SIGNER_ERROR), "add signer error"},
|
||||
{ERR_REASON(CMS_R_CERTIFICATE_ALREADY_PRESENT),
|
||||
"certificate already present"},
|
||||
{ERR_REASON(CMS_R_CERTIFICATE_HAS_NO_KEYID), "certificate has no keyid"},
|
||||
{ERR_REASON(CMS_R_CERTIFICATE_VERIFY_ERROR), "certificate verify error"},
|
||||
{ERR_REASON(CMS_R_CIPHER_INITIALISATION_ERROR),
|
||||
"cipher initialisation error"},
|
||||
{ERR_REASON(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),
|
||||
"cipher parameter initialisation error"},
|
||||
{ERR_REASON(CMS_R_CMS_DATAFINAL_ERROR), "cms datafinal error"},
|
||||
{ERR_REASON(CMS_R_CMS_LIB), "cms lib"},
|
||||
{ERR_REASON(CMS_R_CONTENTIDENTIFIER_MISMATCH),
|
||||
"contentidentifier mismatch"},
|
||||
{ERR_REASON(CMS_R_CONTENT_NOT_FOUND), "content not found"},
|
||||
{ERR_REASON(CMS_R_CONTENT_TYPE_MISMATCH), "content type mismatch"},
|
||||
{ERR_REASON(CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA),
|
||||
"content type not compressed data"},
|
||||
{ERR_REASON(CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA),
|
||||
"content type not enveloped data"},
|
||||
{ERR_REASON(CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA),
|
||||
"content type not signed data"},
|
||||
{ERR_REASON(CMS_R_CONTENT_VERIFY_ERROR), "content verify error"},
|
||||
{ERR_REASON(CMS_R_CTRL_ERROR), "ctrl error"},
|
||||
{ERR_REASON(CMS_R_CTRL_FAILURE), "ctrl failure"},
|
||||
{ERR_REASON(CMS_R_DECRYPT_ERROR), "decrypt error"},
|
||||
{ERR_REASON(CMS_R_DIGEST_ERROR), "digest error"},
|
||||
{ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY), "error getting public key"},
|
||||
{ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),
|
||||
"error reading messagedigest attribute"},
|
||||
{ERR_REASON(CMS_R_ERROR_SETTING_KEY), "error setting key"},
|
||||
{ERR_REASON(CMS_R_ERROR_SETTING_RECIPIENTINFO),
|
||||
"error setting recipientinfo"},
|
||||
{ERR_REASON(CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),
|
||||
"invalid encrypted key length"},
|
||||
{ERR_REASON(CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),
|
||||
"invalid key encryption parameter"},
|
||||
{ERR_REASON(CMS_R_INVALID_KEY_LENGTH), "invalid key length"},
|
||||
{ERR_REASON(CMS_R_MD_BIO_INIT_ERROR), "md bio init error"},
|
||||
{ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),
|
||||
"messagedigest attribute wrong length"},
|
||||
{ERR_REASON(CMS_R_MESSAGEDIGEST_WRONG_LENGTH),
|
||||
"messagedigest wrong length"},
|
||||
{ERR_REASON(CMS_R_MSGSIGDIGEST_ERROR), "msgsigdigest error"},
|
||||
{ERR_REASON(CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE),
|
||||
"msgsigdigest verification failure"},
|
||||
{ERR_REASON(CMS_R_MSGSIGDIGEST_WRONG_LENGTH),
|
||||
"msgsigdigest wrong length"},
|
||||
{ERR_REASON(CMS_R_NEED_ONE_SIGNER), "need one signer"},
|
||||
{ERR_REASON(CMS_R_NOT_A_SIGNED_RECEIPT), "not a signed receipt"},
|
||||
{ERR_REASON(CMS_R_NOT_ENCRYPTED_DATA), "not encrypted data"},
|
||||
{ERR_REASON(CMS_R_NOT_KEK), "not kek"},
|
||||
{ERR_REASON(CMS_R_NOT_KEY_AGREEMENT), "not key agreement"},
|
||||
{ERR_REASON(CMS_R_NOT_KEY_TRANSPORT), "not key transport"},
|
||||
{ERR_REASON(CMS_R_NOT_PWRI), "not pwri"},
|
||||
{ERR_REASON(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),
|
||||
"not supported for this key type"},
|
||||
{ERR_REASON(CMS_R_NO_CIPHER), "no cipher"},
|
||||
{ERR_REASON(CMS_R_NO_CONTENT), "no content"},
|
||||
{ERR_REASON(CMS_R_NO_CONTENT_TYPE), "no content type"},
|
||||
{ERR_REASON(CMS_R_NO_DEFAULT_DIGEST), "no default digest"},
|
||||
{ERR_REASON(CMS_R_NO_DIGEST_SET), "no digest set"},
|
||||
{ERR_REASON(CMS_R_NO_KEY), "no key"},
|
||||
{ERR_REASON(CMS_R_NO_KEY_OR_CERT), "no key or cert"},
|
||||
{ERR_REASON(CMS_R_NO_MATCHING_DIGEST), "no matching digest"},
|
||||
{ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT), "no matching recipient"},
|
||||
{ERR_REASON(CMS_R_NO_MATCHING_SIGNATURE), "no matching signature"},
|
||||
{ERR_REASON(CMS_R_NO_MSGSIGDIGEST), "no msgsigdigest"},
|
||||
{ERR_REASON(CMS_R_NO_PASSWORD), "no password"},
|
||||
{ERR_REASON(CMS_R_NO_PRIVATE_KEY), "no private key"},
|
||||
{ERR_REASON(CMS_R_NO_PUBLIC_KEY), "no public key"},
|
||||
{ERR_REASON(CMS_R_NO_RECEIPT_REQUEST), "no receipt request"},
|
||||
{ERR_REASON(CMS_R_NO_SIGNERS), "no signers"},
|
||||
{ERR_REASON(CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),
|
||||
"private key does not match certificate"},
|
||||
{ERR_REASON(CMS_R_RECEIPT_DECODE_ERROR), "receipt decode error"},
|
||||
{ERR_REASON(CMS_R_RECIPIENT_ERROR), "recipient error"},
|
||||
{ERR_REASON(CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),
|
||||
"signer certificate not found"},
|
||||
{ERR_REASON(CMS_R_SIGNFINAL_ERROR), "signfinal error"},
|
||||
{ERR_REASON(CMS_R_SMIME_TEXT_ERROR), "smime text error"},
|
||||
{ERR_REASON(CMS_R_STORE_INIT_ERROR), "store init error"},
|
||||
{ERR_REASON(CMS_R_TYPE_NOT_COMPRESSED_DATA), "type not compressed data"},
|
||||
{ERR_REASON(CMS_R_TYPE_NOT_DATA), "type not data"},
|
||||
{ERR_REASON(CMS_R_TYPE_NOT_DIGESTED_DATA), "type not digested data"},
|
||||
{ERR_REASON(CMS_R_TYPE_NOT_ENCRYPTED_DATA), "type not encrypted data"},
|
||||
{ERR_REASON(CMS_R_TYPE_NOT_ENVELOPED_DATA), "type not enveloped data"},
|
||||
{ERR_REASON(CMS_R_UNABLE_TO_FINALIZE_CONTEXT),
|
||||
"unable to finalize context"},
|
||||
{ERR_REASON(CMS_R_UNKNOWN_CIPHER), "unknown cipher"},
|
||||
{ERR_REASON(CMS_R_UNKNOWN_DIGEST_ALGORIHM), "unknown digest algorihm"},
|
||||
{ERR_REASON(CMS_R_UNKNOWN_ID), "unknown id"},
|
||||
{ERR_REASON(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),
|
||||
"unsupported compression algorithm"},
|
||||
{ERR_REASON(CMS_R_UNSUPPORTED_CONTENT_TYPE), "unsupported content type"},
|
||||
{ERR_REASON(CMS_R_UNSUPPORTED_KEK_ALGORITHM),
|
||||
"unsupported kek algorithm"},
|
||||
{ERR_REASON(CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),
|
||||
"unsupported key encryption algorithm"},
|
||||
{ERR_REASON(CMS_R_UNSUPPORTED_RECIPIENT_TYPE),
|
||||
"unsupported recipient type"},
|
||||
{ERR_REASON(CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE),
|
||||
"unsupported recpientinfo type"},
|
||||
{ERR_REASON(CMS_R_UNSUPPORTED_TYPE), "unsupported type"},
|
||||
{ERR_REASON(CMS_R_UNWRAP_ERROR), "unwrap error"},
|
||||
{ERR_REASON(CMS_R_UNWRAP_FAILURE), "unwrap failure"},
|
||||
{ERR_REASON(CMS_R_VERIFICATION_FAILURE), "verification failure"},
|
||||
{ERR_REASON(CMS_R_WRAP_ERROR), "wrap error"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void ERR_load_CMS_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
if (ERR_func_error_string(CMS_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings(0, CMS_str_functs);
|
||||
ERR_load_strings(0, CMS_str_reasons);
|
||||
}
|
||||
#endif
|
||||
}
|
394
cms/lib/cms_ess.c
Normal file
394
cms/lib/cms_ess.c
Normal file
|
@ -0,0 +1,394 @@
|
|||
/* crypto/cms/cms_ess.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_ReceiptRequest)
|
||||
DECLARE_ASN1_ITEM(CMS_Receipt)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)
|
||||
|
||||
/* ESS services: for now just Signed Receipt related */
|
||||
|
||||
int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
|
||||
{
|
||||
ASN1_STRING *str;
|
||||
CMS_ReceiptRequest *rr = NULL;
|
||||
if (prr)
|
||||
*prr = NULL;
|
||||
str = CMS_signed_get0_data_by_OBJ(si,
|
||||
OBJ_nid2obj
|
||||
(NID_id_smime_aa_receiptRequest), -3,
|
||||
V_ASN1_SEQUENCE);
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest));
|
||||
if (!rr)
|
||||
return -1;
|
||||
if (prr)
|
||||
*prr = rr;
|
||||
else
|
||||
CMS_ReceiptRequest_free(rr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
|
||||
int allorfirst,
|
||||
STACK_OF(GENERAL_NAMES)
|
||||
*receiptList, STACK_OF(GENERAL_NAMES)
|
||||
*receiptsTo)
|
||||
{
|
||||
CMS_ReceiptRequest *rr = NULL;
|
||||
|
||||
rr = CMS_ReceiptRequest_new();
|
||||
if (!rr)
|
||||
goto merr;
|
||||
if (id)
|
||||
ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen);
|
||||
else {
|
||||
if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
|
||||
goto merr;
|
||||
if (RAND_bytes(rr->signedContentIdentifier->data, 32) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
|
||||
rr->receiptsTo = receiptsTo;
|
||||
|
||||
if (receiptList) {
|
||||
rr->receiptsFrom->type = 1;
|
||||
rr->receiptsFrom->d.receiptList = receiptList;
|
||||
} else {
|
||||
rr->receiptsFrom->type = 0;
|
||||
rr->receiptsFrom->d.allOrFirstTier = allorfirst;
|
||||
}
|
||||
|
||||
return rr;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
err:
|
||||
if (rr)
|
||||
CMS_ReceiptRequest_free(rr);
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
|
||||
{
|
||||
unsigned char *rrder = NULL;
|
||||
int rrderlen, r = 0;
|
||||
|
||||
rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder);
|
||||
if (rrderlen < 0)
|
||||
goto merr;
|
||||
|
||||
if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest,
|
||||
V_ASN1_SEQUENCE, rrder, rrderlen))
|
||||
goto merr;
|
||||
|
||||
r = 1;
|
||||
|
||||
merr:
|
||||
if (!r)
|
||||
CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
if (rrder)
|
||||
OPENSSL_free(rrder);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
|
||||
ASN1_STRING **pcid,
|
||||
int *pallorfirst,
|
||||
STACK_OF(GENERAL_NAMES) **plist,
|
||||
STACK_OF(GENERAL_NAMES) **prto)
|
||||
{
|
||||
if (pcid)
|
||||
*pcid = rr->signedContentIdentifier;
|
||||
if (rr->receiptsFrom->type == 0) {
|
||||
if (pallorfirst)
|
||||
*pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
|
||||
if (plist)
|
||||
*plist = NULL;
|
||||
} else {
|
||||
if (pallorfirst)
|
||||
*pallorfirst = -1;
|
||||
if (plist)
|
||||
*plist = rr->receiptsFrom->d.receiptList;
|
||||
}
|
||||
if (prto)
|
||||
*prto = rr->receiptsTo;
|
||||
}
|
||||
|
||||
/* Digest a SignerInfo structure for msgSigDigest attribute processing */
|
||||
|
||||
static int cms_msgSigDigest(CMS_SignerInfo *si,
|
||||
unsigned char *dig, unsigned int *diglen)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
|
||||
if (md == NULL)
|
||||
return 0;
|
||||
if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
|
||||
si->signedAttrs, dig, diglen))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add a msgSigDigest attribute to a SignerInfo */
|
||||
|
||||
int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src)
|
||||
{
|
||||
unsigned char dig[EVP_MAX_MD_SIZE];
|
||||
unsigned int diglen;
|
||||
if (!cms_msgSigDigest(src, dig, &diglen)) {
|
||||
CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest,
|
||||
V_ASN1_OCTET_STRING, dig, diglen)) {
|
||||
CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Verify signed receipt after it has already passed normal CMS verify */
|
||||
|
||||
int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
|
||||
{
|
||||
int r = 0, i;
|
||||
CMS_ReceiptRequest *rr = NULL;
|
||||
CMS_Receipt *rct = NULL;
|
||||
STACK_OF(CMS_SignerInfo) *sis, *osis;
|
||||
CMS_SignerInfo *si, *osi = NULL;
|
||||
ASN1_OCTET_STRING *msig, **pcont;
|
||||
ASN1_OBJECT *octype;
|
||||
unsigned char dig[EVP_MAX_MD_SIZE];
|
||||
unsigned int diglen;
|
||||
|
||||
/* Get SignerInfos, also checks SignedData content type */
|
||||
osis = CMS_get0_SignerInfos(req_cms);
|
||||
sis = CMS_get0_SignerInfos(cms);
|
||||
if (!osis || !sis)
|
||||
goto err;
|
||||
|
||||
if (sk_CMS_SignerInfo_num(sis) != 1) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NEED_ONE_SIGNER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check receipt content type */
|
||||
if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NOT_A_SIGNED_RECEIPT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Extract and decode receipt content */
|
||||
pcont = CMS_get0_content(cms);
|
||||
if (!pcont || !*pcont) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rct = ASN1_item_unpack(*pcont, ASN1_ITEM_rptr(CMS_Receipt));
|
||||
|
||||
if (!rct) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_RECEIPT_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Locate original request */
|
||||
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(osis); i++) {
|
||||
osi = sk_CMS_SignerInfo_value(osis, i);
|
||||
if (!ASN1_STRING_cmp(osi->signature, rct->originatorSignatureValue))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sk_CMS_SignerInfo_num(osis)) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MATCHING_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
si = sk_CMS_SignerInfo_value(sis, 0);
|
||||
|
||||
/* Get msgSigDigest value and compare */
|
||||
|
||||
msig = CMS_signed_get0_data_by_OBJ(si,
|
||||
OBJ_nid2obj
|
||||
(NID_id_smime_aa_msgSigDigest), -3,
|
||||
V_ASN1_OCTET_STRING);
|
||||
|
||||
if (!msig) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MSGSIGDIGEST);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!cms_msgSigDigest(osi, dig, &diglen)) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (diglen != (unsigned int)msig->length) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_WRONG_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(dig, msig->data, diglen)) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY,
|
||||
CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Compare content types */
|
||||
|
||||
octype = CMS_signed_get0_data_by_OBJ(osi,
|
||||
OBJ_nid2obj(NID_pkcs9_contentType),
|
||||
-3, V_ASN1_OBJECT);
|
||||
if (!octype) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Compare details in receipt request */
|
||||
|
||||
if (OBJ_cmp(octype, rct->contentType)) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENT_TYPE_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get original receipt request details */
|
||||
|
||||
if (CMS_get1_ReceiptRequest(osi, &rr) <= 0) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_RECEIPT_REQUEST);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ASN1_STRING_cmp(rr->signedContentIdentifier,
|
||||
rct->signedContentIdentifier)) {
|
||||
CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENTIDENTIFIER_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
if (rr)
|
||||
CMS_ReceiptRequest_free(rr);
|
||||
if (rct)
|
||||
M_ASN1_free_of(rct, CMS_Receipt);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a Receipt into an OCTET STRING read for including into content of a
|
||||
* SignedData ContentInfo.
|
||||
*/
|
||||
|
||||
ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
|
||||
{
|
||||
CMS_Receipt rct;
|
||||
CMS_ReceiptRequest *rr = NULL;
|
||||
ASN1_OBJECT *ctype;
|
||||
ASN1_OCTET_STRING *os = NULL;
|
||||
|
||||
/* Get original receipt request */
|
||||
|
||||
/* Get original receipt request details */
|
||||
|
||||
if (CMS_get1_ReceiptRequest(si, &rr) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get original content type */
|
||||
|
||||
ctype = CMS_signed_get0_data_by_OBJ(si,
|
||||
OBJ_nid2obj(NID_pkcs9_contentType),
|
||||
-3, V_ASN1_OBJECT);
|
||||
if (!ctype) {
|
||||
CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rct.version = 1;
|
||||
rct.contentType = ctype;
|
||||
rct.signedContentIdentifier = rr->signedContentIdentifier;
|
||||
rct.originatorSignatureValue = si->signature;
|
||||
|
||||
os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL);
|
||||
|
||||
err:
|
||||
if (rr)
|
||||
CMS_ReceiptRequest_free(rr);
|
||||
|
||||
return os;
|
||||
|
||||
}
|
133
cms/lib/cms_io.c
Normal file
133
cms/lib/cms_io.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* crypto/cms/cms_io.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
|
||||
int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos;
|
||||
pos = CMS_get0_content(cms);
|
||||
if (!pos)
|
||||
return 0;
|
||||
if (!*pos)
|
||||
*pos = ASN1_OCTET_STRING_new();
|
||||
if (*pos) {
|
||||
(*pos)->flags |= ASN1_STRING_FLAG_NDEF;
|
||||
(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
|
||||
*boundary = &(*pos)->data;
|
||||
return 1;
|
||||
}
|
||||
CMSerr(CMS_F_CMS_STREAM, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms)
|
||||
{
|
||||
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
|
||||
}
|
||||
|
||||
int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms)
|
||||
{
|
||||
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
|
||||
}
|
||||
|
||||
IMPLEMENT_PEM_rw_const(CMS, CMS_ContentInfo, PEM_STRING_CMS, CMS_ContentInfo)
|
||||
|
||||
BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms)
|
||||
{
|
||||
return BIO_new_NDEF(out, (ASN1_VALUE *)cms,
|
||||
ASN1_ITEM_rptr(CMS_ContentInfo));
|
||||
}
|
||||
|
||||
/* CMS wrappers round generalised stream and MIME routines */
|
||||
|
||||
int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags)
|
||||
{
|
||||
return i2d_ASN1_bio_stream(out, (ASN1_VALUE *)cms, in, flags,
|
||||
ASN1_ITEM_rptr(CMS_ContentInfo));
|
||||
}
|
||||
|
||||
int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in,
|
||||
int flags)
|
||||
{
|
||||
return PEM_write_bio_ASN1_stream(out, (ASN1_VALUE *)cms, in, flags,
|
||||
"CMS", ASN1_ITEM_rptr(CMS_ContentInfo));
|
||||
}
|
||||
|
||||
int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags)
|
||||
{
|
||||
STACK_OF(X509_ALGOR) *mdalgs;
|
||||
int ctype_nid = OBJ_obj2nid(cms->contentType);
|
||||
int econt_nid = OBJ_obj2nid(CMS_get0_eContentType(cms));
|
||||
if (ctype_nid == NID_pkcs7_signed)
|
||||
mdalgs = cms->d.signedData->digestAlgorithms;
|
||||
else
|
||||
mdalgs = NULL;
|
||||
|
||||
return SMIME_write_ASN1(bio, (ASN1_VALUE *)cms, data, flags,
|
||||
ctype_nid, econt_nid, mdalgs,
|
||||
ASN1_ITEM_rptr(CMS_ContentInfo));
|
||||
}
|
||||
|
||||
CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont)
|
||||
{
|
||||
return (CMS_ContentInfo *)SMIME_read_ASN1(bio, bcont,
|
||||
ASN1_ITEM_rptr
|
||||
(CMS_ContentInfo));
|
||||
}
|
465
cms/lib/cms_kari.c
Normal file
465
cms/lib/cms_kari.c
Normal file
|
@ -0,0 +1,465 @@
|
|||
/* crypto/cms/cms_kari.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2013 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/aes.h>
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_KeyAgreeRecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_RecipientEncryptedKey)
|
||||
DECLARE_ASN1_ITEM(CMS_OriginatorPublicKey)
|
||||
DECLARE_ASN1_ITEM(CMS_RecipientKeyIdentifier)
|
||||
|
||||
/* Key Agreement Recipient Info (KARI) routines */
|
||||
|
||||
int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
|
||||
X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pukm)
|
||||
{
|
||||
if (ri->type != CMS_RECIPINFO_AGREE) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG,
|
||||
CMS_R_NOT_KEY_AGREEMENT);
|
||||
return 0;
|
||||
}
|
||||
if (palg)
|
||||
*palg = ri->d.kari->keyEncryptionAlgorithm;
|
||||
if (pukm)
|
||||
*pukm = ri->d.kari->ukm;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Retrieve recipient encrypted keys from a kari */
|
||||
|
||||
STACK_OF(CMS_RecipientEncryptedKey)
|
||||
*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri)
|
||||
{
|
||||
if (ri->type != CMS_RECIPINFO_AGREE) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS,
|
||||
CMS_R_NOT_KEY_AGREEMENT);
|
||||
return NULL;
|
||||
}
|
||||
return ri->d.kari->recipientEncryptedKeys;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
|
||||
X509_ALGOR **pubalg,
|
||||
ASN1_BIT_STRING **pubkey,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer,
|
||||
ASN1_INTEGER **sno)
|
||||
{
|
||||
CMS_OriginatorIdentifierOrKey *oik;
|
||||
if (ri->type != CMS_RECIPINFO_AGREE) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID,
|
||||
CMS_R_NOT_KEY_AGREEMENT);
|
||||
return 0;
|
||||
}
|
||||
oik = ri->d.kari->originator;
|
||||
if (issuer)
|
||||
*issuer = NULL;
|
||||
if (sno)
|
||||
*sno = NULL;
|
||||
if (keyid)
|
||||
*keyid = NULL;
|
||||
if (pubalg)
|
||||
*pubalg = NULL;
|
||||
if (pubkey)
|
||||
*pubkey = NULL;
|
||||
if (oik->type == CMS_OIK_ISSUER_SERIAL) {
|
||||
if (issuer)
|
||||
*issuer = oik->d.issuerAndSerialNumber->issuer;
|
||||
if (sno)
|
||||
*sno = oik->d.issuerAndSerialNumber->serialNumber;
|
||||
} else if (oik->type == CMS_OIK_KEYIDENTIFIER) {
|
||||
if (keyid)
|
||||
*keyid = oik->d.subjectKeyIdentifier;
|
||||
} else if (oik->type == CMS_OIK_PUBKEY) {
|
||||
if (pubalg)
|
||||
*pubalg = oik->d.originatorKey->algorithm;
|
||||
if (pubkey)
|
||||
*pubkey = oik->d.originatorKey->publicKey;
|
||||
} else
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
|
||||
{
|
||||
CMS_OriginatorIdentifierOrKey *oik;
|
||||
if (ri->type != CMS_RECIPINFO_AGREE) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP,
|
||||
CMS_R_NOT_KEY_AGREEMENT);
|
||||
return -2;
|
||||
}
|
||||
oik = ri->d.kari->originator;
|
||||
if (oik->type == CMS_OIK_ISSUER_SERIAL)
|
||||
return cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert);
|
||||
else if (oik->type == CMS_OIK_KEYIDENTIFIER)
|
||||
return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
ASN1_GENERALIZEDTIME **tm,
|
||||
CMS_OtherKeyAttribute **other,
|
||||
X509_NAME **issuer, ASN1_INTEGER **sno)
|
||||
{
|
||||
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
|
||||
if (rid->type == CMS_REK_ISSUER_SERIAL) {
|
||||
if (issuer)
|
||||
*issuer = rid->d.issuerAndSerialNumber->issuer;
|
||||
if (sno)
|
||||
*sno = rid->d.issuerAndSerialNumber->serialNumber;
|
||||
if (keyid)
|
||||
*keyid = NULL;
|
||||
if (tm)
|
||||
*tm = NULL;
|
||||
if (other)
|
||||
*other = NULL;
|
||||
} else if (rid->type == CMS_REK_KEYIDENTIFIER) {
|
||||
if (keyid)
|
||||
*keyid = rid->d.rKeyId->subjectKeyIdentifier;
|
||||
if (tm)
|
||||
*tm = rid->d.rKeyId->date;
|
||||
if (other)
|
||||
*other = rid->d.rKeyId->other;
|
||||
if (issuer)
|
||||
*issuer = NULL;
|
||||
if (sno)
|
||||
*sno = NULL;
|
||||
} else
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
|
||||
X509 *cert)
|
||||
{
|
||||
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
|
||||
if (rid->type == CMS_REK_ISSUER_SERIAL)
|
||||
return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
|
||||
else if (rid->type == CMS_REK_KEYIDENTIFIER)
|
||||
return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx;
|
||||
CMS_KeyAgreeRecipientInfo *kari = ri->d.kari;
|
||||
if (kari->pctx) {
|
||||
EVP_PKEY_CTX_free(kari->pctx);
|
||||
kari->pctx = NULL;
|
||||
}
|
||||
if (!pk)
|
||||
return 1;
|
||||
pctx = EVP_PKEY_CTX_new(pk, NULL);
|
||||
if (!pctx || !EVP_PKEY_derive_init(pctx))
|
||||
goto err;
|
||||
kari->pctx = pctx;
|
||||
return 1;
|
||||
err:
|
||||
if (pctx)
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri)
|
||||
{
|
||||
if (ri->type == CMS_RECIPINFO_AGREE)
|
||||
return &ri->d.kari->ctx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Derive KEK and decrypt/encrypt with it to produce either the original CEK
|
||||
* or the encrypted CEK.
|
||||
*/
|
||||
|
||||
static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
|
||||
const unsigned char *in, size_t inlen,
|
||||
CMS_KeyAgreeRecipientInfo *kari, int enc)
|
||||
{
|
||||
/* Key encryption key */
|
||||
unsigned char kek[EVP_MAX_KEY_LENGTH];
|
||||
size_t keklen;
|
||||
int rv = 0;
|
||||
unsigned char *out = NULL;
|
||||
int outlen;
|
||||
keklen = EVP_CIPHER_CTX_key_length(&kari->ctx);
|
||||
if (keklen > EVP_MAX_KEY_LENGTH)
|
||||
return 0;
|
||||
/* Derive KEK */
|
||||
if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0)
|
||||
goto err;
|
||||
/* Set KEK in context */
|
||||
if (!EVP_CipherInit_ex(&kari->ctx, NULL, NULL, kek, NULL, enc))
|
||||
goto err;
|
||||
/* obtain output length of ciphered key */
|
||||
if (!EVP_CipherUpdate(&kari->ctx, NULL, &outlen, in, inlen))
|
||||
goto err;
|
||||
out = OPENSSL_malloc(outlen);
|
||||
if (!out)
|
||||
goto err;
|
||||
if (!EVP_CipherUpdate(&kari->ctx, out, &outlen, in, inlen))
|
||||
goto err;
|
||||
*pout = out;
|
||||
*poutlen = (size_t)outlen;
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_cleanse(kek, keklen);
|
||||
if (!rv && out)
|
||||
OPENSSL_free(out);
|
||||
EVP_CIPHER_CTX_cleanup(&kari->ctx);
|
||||
EVP_PKEY_CTX_free(kari->pctx);
|
||||
kari->pctx = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri,
|
||||
CMS_RecipientEncryptedKey *rek)
|
||||
{
|
||||
int rv = 0;
|
||||
unsigned char *enckey = NULL, *cek = NULL;
|
||||
size_t enckeylen;
|
||||
size_t ceklen;
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
enckeylen = rek->encryptedKey->length;
|
||||
enckey = rek->encryptedKey->data;
|
||||
/* Setup all parameters to derive KEK */
|
||||
if (!cms_env_asn1_ctrl(ri, 1))
|
||||
goto err;
|
||||
/* Attempt to decrypt CEK */
|
||||
if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0))
|
||||
goto err;
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
if (ec->key) {
|
||||
OPENSSL_cleanse(ec->key, ec->keylen);
|
||||
OPENSSL_free(ec->key);
|
||||
}
|
||||
ec->key = cek;
|
||||
ec->keylen = ceklen;
|
||||
cek = NULL;
|
||||
rv = 1;
|
||||
err:
|
||||
if (cek)
|
||||
OPENSSL_free(cek);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Create ephemeral key and initialise context based on it */
|
||||
static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
|
||||
EVP_PKEY *pk)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *ekey = NULL;
|
||||
int rv = 0;
|
||||
pctx = EVP_PKEY_CTX_new(pk, NULL);
|
||||
if (!pctx)
|
||||
goto err;
|
||||
if (EVP_PKEY_keygen_init(pctx) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_keygen(pctx, &ekey) <= 0)
|
||||
goto err;
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
pctx = EVP_PKEY_CTX_new(ekey, NULL);
|
||||
if (!pctx)
|
||||
goto err;
|
||||
if (EVP_PKEY_derive_init(pctx) <= 0)
|
||||
goto err;
|
||||
kari->pctx = pctx;
|
||||
rv = 1;
|
||||
err:
|
||||
if (!rv && pctx)
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (ekey)
|
||||
EVP_PKEY_free(ekey);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Initialise a ktri based on passed certificate and key */
|
||||
|
||||
int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
|
||||
EVP_PKEY *pk, unsigned int flags)
|
||||
{
|
||||
CMS_KeyAgreeRecipientInfo *kari;
|
||||
CMS_RecipientEncryptedKey *rek = NULL;
|
||||
|
||||
ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo);
|
||||
if (!ri->d.kari)
|
||||
return 0;
|
||||
ri->type = CMS_RECIPINFO_AGREE;
|
||||
|
||||
kari = ri->d.kari;
|
||||
kari->version = 3;
|
||||
|
||||
rek = M_ASN1_new_of(CMS_RecipientEncryptedKey);
|
||||
if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) {
|
||||
M_ASN1_free_of(rek, CMS_RecipientEncryptedKey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & CMS_USE_KEYID) {
|
||||
rek->rid->type = CMS_REK_KEYIDENTIFIER;
|
||||
rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier);
|
||||
if (rek->rid->d.rKeyId == NULL)
|
||||
return 0;
|
||||
if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip))
|
||||
return 0;
|
||||
} else {
|
||||
rek->rid->type = CMS_REK_ISSUER_SERIAL;
|
||||
if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create ephemeral key */
|
||||
if (!cms_kari_create_ephemeral_key(kari, pk))
|
||||
return 0;
|
||||
|
||||
CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
|
||||
rek->pkey = pk;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
|
||||
const EVP_CIPHER *cipher)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx = &kari->ctx;
|
||||
const EVP_CIPHER *kekcipher;
|
||||
int keylen = EVP_CIPHER_key_length(cipher);
|
||||
/* If a suitable wrap algorithm is already set nothing to do */
|
||||
kekcipher = EVP_CIPHER_CTX_cipher(ctx);
|
||||
|
||||
if (kekcipher) {
|
||||
if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Pick a cipher based on content encryption cipher. If it is DES3 use
|
||||
* DES3 wrap otherwise use AES wrap similar to key size.
|
||||
*/
|
||||
if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc)
|
||||
kekcipher = EVP_des_ede3_wrap();
|
||||
else if (keylen <= 16)
|
||||
kekcipher = EVP_aes_128_wrap();
|
||||
else if (keylen <= 24)
|
||||
kekcipher = EVP_aes_192_wrap();
|
||||
else
|
||||
kekcipher = EVP_aes_256_wrap();
|
||||
return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Encrypt content key in key agreement recipient info */
|
||||
|
||||
int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri)
|
||||
{
|
||||
CMS_KeyAgreeRecipientInfo *kari;
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
CMS_RecipientEncryptedKey *rek;
|
||||
STACK_OF(CMS_RecipientEncryptedKey) *reks;
|
||||
int i;
|
||||
|
||||
if (ri->type != CMS_RECIPINFO_AGREE) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT);
|
||||
return 0;
|
||||
}
|
||||
kari = ri->d.kari;
|
||||
reks = kari->recipientEncryptedKeys;
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
/* Initialise wrap algorithm parameters */
|
||||
if (!cms_wrap_init(kari, ec->cipher))
|
||||
return 0;
|
||||
/*
|
||||
* If no orignator key set up initialise for ephemeral key the public key
|
||||
* ASN1 structure will set the actual public key value.
|
||||
*/
|
||||
if (kari->originator->type == -1) {
|
||||
CMS_OriginatorIdentifierOrKey *oik = kari->originator;
|
||||
oik->type = CMS_OIK_PUBKEY;
|
||||
oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey);
|
||||
if (!oik->d.originatorKey)
|
||||
return 0;
|
||||
}
|
||||
/* Initialise KDF algorithm */
|
||||
if (!cms_env_asn1_ctrl(ri, 0))
|
||||
return 0;
|
||||
/* For each rek, derive KEK, encrypt CEK */
|
||||
for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
|
||||
unsigned char *enckey;
|
||||
size_t enckeylen;
|
||||
rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
|
||||
if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0)
|
||||
return 0;
|
||||
if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen,
|
||||
kari, 1))
|
||||
return 0;
|
||||
ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
471
cms/lib/cms_lcl.h
Normal file
471
cms/lib/cms_lcl.h
Normal file
|
@ -0,0 +1,471 @@
|
|||
/* crypto/cms/cms_lcl.h */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#ifndef HEADER_CMS_LCL_H
|
||||
# define HEADER_CMS_LCL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
# include <openssl/x509.h>
|
||||
|
||||
/*
|
||||
* Cryptographic message syntax (CMS) structures: taken from RFC3852
|
||||
*/
|
||||
|
||||
/* Forward references */
|
||||
|
||||
typedef struct CMS_IssuerAndSerialNumber_st CMS_IssuerAndSerialNumber;
|
||||
typedef struct CMS_EncapsulatedContentInfo_st CMS_EncapsulatedContentInfo;
|
||||
typedef struct CMS_SignerIdentifier_st CMS_SignerIdentifier;
|
||||
typedef struct CMS_SignedData_st CMS_SignedData;
|
||||
typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat;
|
||||
typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo;
|
||||
typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo;
|
||||
typedef struct CMS_EnvelopedData_st CMS_EnvelopedData;
|
||||
typedef struct CMS_DigestedData_st CMS_DigestedData;
|
||||
typedef struct CMS_EncryptedData_st CMS_EncryptedData;
|
||||
typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData;
|
||||
typedef struct CMS_CompressedData_st CMS_CompressedData;
|
||||
typedef struct CMS_OtherCertificateFormat_st CMS_OtherCertificateFormat;
|
||||
typedef struct CMS_KeyTransRecipientInfo_st CMS_KeyTransRecipientInfo;
|
||||
typedef struct CMS_OriginatorPublicKey_st CMS_OriginatorPublicKey;
|
||||
typedef struct CMS_OriginatorIdentifierOrKey_st CMS_OriginatorIdentifierOrKey;
|
||||
typedef struct CMS_KeyAgreeRecipientInfo_st CMS_KeyAgreeRecipientInfo;
|
||||
typedef struct CMS_RecipientKeyIdentifier_st CMS_RecipientKeyIdentifier;
|
||||
typedef struct CMS_KeyAgreeRecipientIdentifier_st
|
||||
CMS_KeyAgreeRecipientIdentifier;
|
||||
typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier;
|
||||
typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo;
|
||||
typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo;
|
||||
typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo;
|
||||
typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom;
|
||||
|
||||
struct CMS_ContentInfo_st {
|
||||
ASN1_OBJECT *contentType;
|
||||
union {
|
||||
ASN1_OCTET_STRING *data;
|
||||
CMS_SignedData *signedData;
|
||||
CMS_EnvelopedData *envelopedData;
|
||||
CMS_DigestedData *digestedData;
|
||||
CMS_EncryptedData *encryptedData;
|
||||
CMS_AuthenticatedData *authenticatedData;
|
||||
CMS_CompressedData *compressedData;
|
||||
ASN1_TYPE *other;
|
||||
/* Other types ... */
|
||||
void *otherData;
|
||||
} d;
|
||||
};
|
||||
|
||||
struct CMS_SignedData_st {
|
||||
long version;
|
||||
STACK_OF(X509_ALGOR) *digestAlgorithms;
|
||||
CMS_EncapsulatedContentInfo *encapContentInfo;
|
||||
STACK_OF(CMS_CertificateChoices) *certificates;
|
||||
STACK_OF(CMS_RevocationInfoChoice) *crls;
|
||||
STACK_OF(CMS_SignerInfo) *signerInfos;
|
||||
};
|
||||
|
||||
struct CMS_EncapsulatedContentInfo_st {
|
||||
ASN1_OBJECT *eContentType;
|
||||
ASN1_OCTET_STRING *eContent;
|
||||
/* Set to 1 if incomplete structure only part set up */
|
||||
int partial;
|
||||
};
|
||||
|
||||
struct CMS_SignerInfo_st {
|
||||
long version;
|
||||
CMS_SignerIdentifier *sid;
|
||||
X509_ALGOR *digestAlgorithm;
|
||||
STACK_OF(X509_ATTRIBUTE) *signedAttrs;
|
||||
X509_ALGOR *signatureAlgorithm;
|
||||
ASN1_OCTET_STRING *signature;
|
||||
STACK_OF(X509_ATTRIBUTE) *unsignedAttrs;
|
||||
/* Signing certificate and key */
|
||||
X509 *signer;
|
||||
EVP_PKEY *pkey;
|
||||
/* Digest and public key context for alternative parameters */
|
||||
EVP_MD_CTX mctx;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
};
|
||||
|
||||
struct CMS_SignerIdentifier_st {
|
||||
int type;
|
||||
union {
|
||||
CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
|
||||
ASN1_OCTET_STRING *subjectKeyIdentifier;
|
||||
} d;
|
||||
};
|
||||
|
||||
struct CMS_EnvelopedData_st {
|
||||
long version;
|
||||
CMS_OriginatorInfo *originatorInfo;
|
||||
STACK_OF(CMS_RecipientInfo) *recipientInfos;
|
||||
CMS_EncryptedContentInfo *encryptedContentInfo;
|
||||
STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs;
|
||||
};
|
||||
|
||||
struct CMS_OriginatorInfo_st {
|
||||
STACK_OF(CMS_CertificateChoices) *certificates;
|
||||
STACK_OF(CMS_RevocationInfoChoice) *crls;
|
||||
};
|
||||
|
||||
struct CMS_EncryptedContentInfo_st {
|
||||
ASN1_OBJECT *contentType;
|
||||
X509_ALGOR *contentEncryptionAlgorithm;
|
||||
ASN1_OCTET_STRING *encryptedContent;
|
||||
/* Content encryption algorithm and key */
|
||||
const EVP_CIPHER *cipher;
|
||||
unsigned char *key;
|
||||
size_t keylen;
|
||||
/* Set to 1 if we are debugging decrypt and don't fake keys for MMA */
|
||||
int debug;
|
||||
};
|
||||
|
||||
struct CMS_RecipientInfo_st {
|
||||
int type;
|
||||
union {
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
CMS_KeyAgreeRecipientInfo *kari;
|
||||
CMS_KEKRecipientInfo *kekri;
|
||||
CMS_PasswordRecipientInfo *pwri;
|
||||
CMS_OtherRecipientInfo *ori;
|
||||
} d;
|
||||
};
|
||||
|
||||
typedef CMS_SignerIdentifier CMS_RecipientIdentifier;
|
||||
|
||||
struct CMS_KeyTransRecipientInfo_st {
|
||||
long version;
|
||||
CMS_RecipientIdentifier *rid;
|
||||
X509_ALGOR *keyEncryptionAlgorithm;
|
||||
ASN1_OCTET_STRING *encryptedKey;
|
||||
/* Recipient Key and cert */
|
||||
X509 *recip;
|
||||
EVP_PKEY *pkey;
|
||||
/* Public key context for this operation */
|
||||
EVP_PKEY_CTX *pctx;
|
||||
};
|
||||
|
||||
struct CMS_KeyAgreeRecipientInfo_st {
|
||||
long version;
|
||||
CMS_OriginatorIdentifierOrKey *originator;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
X509_ALGOR *keyEncryptionAlgorithm;
|
||||
STACK_OF(CMS_RecipientEncryptedKey) *recipientEncryptedKeys;
|
||||
/* Public key context associated with current operation */
|
||||
EVP_PKEY_CTX *pctx;
|
||||
/* Cipher context for CEK wrapping */
|
||||
EVP_CIPHER_CTX ctx;
|
||||
};
|
||||
|
||||
struct CMS_OriginatorIdentifierOrKey_st {
|
||||
int type;
|
||||
union {
|
||||
CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
|
||||
ASN1_OCTET_STRING *subjectKeyIdentifier;
|
||||
CMS_OriginatorPublicKey *originatorKey;
|
||||
} d;
|
||||
};
|
||||
|
||||
struct CMS_OriginatorPublicKey_st {
|
||||
X509_ALGOR *algorithm;
|
||||
ASN1_BIT_STRING *publicKey;
|
||||
};
|
||||
|
||||
struct CMS_RecipientEncryptedKey_st {
|
||||
CMS_KeyAgreeRecipientIdentifier *rid;
|
||||
ASN1_OCTET_STRING *encryptedKey;
|
||||
/* Public key associated with this recipient */
|
||||
EVP_PKEY *pkey;
|
||||
};
|
||||
|
||||
struct CMS_KeyAgreeRecipientIdentifier_st {
|
||||
int type;
|
||||
union {
|
||||
CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
|
||||
CMS_RecipientKeyIdentifier *rKeyId;
|
||||
} d;
|
||||
};
|
||||
|
||||
struct CMS_RecipientKeyIdentifier_st {
|
||||
ASN1_OCTET_STRING *subjectKeyIdentifier;
|
||||
ASN1_GENERALIZEDTIME *date;
|
||||
CMS_OtherKeyAttribute *other;
|
||||
};
|
||||
|
||||
struct CMS_KEKRecipientInfo_st {
|
||||
long version;
|
||||
CMS_KEKIdentifier *kekid;
|
||||
X509_ALGOR *keyEncryptionAlgorithm;
|
||||
ASN1_OCTET_STRING *encryptedKey;
|
||||
/* Extra info: symmetric key to use */
|
||||
unsigned char *key;
|
||||
size_t keylen;
|
||||
};
|
||||
|
||||
struct CMS_KEKIdentifier_st {
|
||||
ASN1_OCTET_STRING *keyIdentifier;
|
||||
ASN1_GENERALIZEDTIME *date;
|
||||
CMS_OtherKeyAttribute *other;
|
||||
};
|
||||
|
||||
struct CMS_PasswordRecipientInfo_st {
|
||||
long version;
|
||||
X509_ALGOR *keyDerivationAlgorithm;
|
||||
X509_ALGOR *keyEncryptionAlgorithm;
|
||||
ASN1_OCTET_STRING *encryptedKey;
|
||||
/* Extra info: password to use */
|
||||
unsigned char *pass;
|
||||
size_t passlen;
|
||||
};
|
||||
|
||||
struct CMS_OtherRecipientInfo_st {
|
||||
ASN1_OBJECT *oriType;
|
||||
ASN1_TYPE *oriValue;
|
||||
};
|
||||
|
||||
struct CMS_DigestedData_st {
|
||||
long version;
|
||||
X509_ALGOR *digestAlgorithm;
|
||||
CMS_EncapsulatedContentInfo *encapContentInfo;
|
||||
ASN1_OCTET_STRING *digest;
|
||||
};
|
||||
|
||||
struct CMS_EncryptedData_st {
|
||||
long version;
|
||||
CMS_EncryptedContentInfo *encryptedContentInfo;
|
||||
STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs;
|
||||
};
|
||||
|
||||
struct CMS_AuthenticatedData_st {
|
||||
long version;
|
||||
CMS_OriginatorInfo *originatorInfo;
|
||||
STACK_OF(CMS_RecipientInfo) *recipientInfos;
|
||||
X509_ALGOR *macAlgorithm;
|
||||
X509_ALGOR *digestAlgorithm;
|
||||
CMS_EncapsulatedContentInfo *encapContentInfo;
|
||||
STACK_OF(X509_ATTRIBUTE) *authAttrs;
|
||||
ASN1_OCTET_STRING *mac;
|
||||
STACK_OF(X509_ATTRIBUTE) *unauthAttrs;
|
||||
};
|
||||
|
||||
struct CMS_CompressedData_st {
|
||||
long version;
|
||||
X509_ALGOR *compressionAlgorithm;
|
||||
STACK_OF(CMS_RecipientInfo) *recipientInfos;
|
||||
CMS_EncapsulatedContentInfo *encapContentInfo;
|
||||
};
|
||||
|
||||
struct CMS_RevocationInfoChoice_st {
|
||||
int type;
|
||||
union {
|
||||
X509_CRL *crl;
|
||||
CMS_OtherRevocationInfoFormat *other;
|
||||
} d;
|
||||
};
|
||||
|
||||
# define CMS_REVCHOICE_CRL 0
|
||||
# define CMS_REVCHOICE_OTHER 1
|
||||
|
||||
struct CMS_OtherRevocationInfoFormat_st {
|
||||
ASN1_OBJECT *otherRevInfoFormat;
|
||||
ASN1_TYPE *otherRevInfo;
|
||||
};
|
||||
|
||||
struct CMS_CertificateChoices {
|
||||
int type;
|
||||
union {
|
||||
X509 *certificate;
|
||||
ASN1_STRING *extendedCertificate; /* Obsolete */
|
||||
ASN1_STRING *v1AttrCert; /* Left encoded for now */
|
||||
ASN1_STRING *v2AttrCert; /* Left encoded for now */
|
||||
CMS_OtherCertificateFormat *other;
|
||||
} d;
|
||||
};
|
||||
|
||||
# define CMS_CERTCHOICE_CERT 0
|
||||
# define CMS_CERTCHOICE_EXCERT 1
|
||||
# define CMS_CERTCHOICE_V1ACERT 2
|
||||
# define CMS_CERTCHOICE_V2ACERT 3
|
||||
# define CMS_CERTCHOICE_OTHER 4
|
||||
|
||||
struct CMS_OtherCertificateFormat_st {
|
||||
ASN1_OBJECT *otherCertFormat;
|
||||
ASN1_TYPE *otherCert;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is also defined in pkcs7.h but we duplicate it to allow the CMS code
|
||||
* to be independent of PKCS#7
|
||||
*/
|
||||
|
||||
struct CMS_IssuerAndSerialNumber_st {
|
||||
X509_NAME *issuer;
|
||||
ASN1_INTEGER *serialNumber;
|
||||
};
|
||||
|
||||
struct CMS_OtherKeyAttribute_st {
|
||||
ASN1_OBJECT *keyAttrId;
|
||||
ASN1_TYPE *keyAttr;
|
||||
};
|
||||
|
||||
/* ESS structures */
|
||||
|
||||
# ifdef HEADER_X509V3_H
|
||||
|
||||
struct CMS_ReceiptRequest_st {
|
||||
ASN1_OCTET_STRING *signedContentIdentifier;
|
||||
CMS_ReceiptsFrom *receiptsFrom;
|
||||
STACK_OF(GENERAL_NAMES) *receiptsTo;
|
||||
};
|
||||
|
||||
struct CMS_ReceiptsFrom_st {
|
||||
int type;
|
||||
union {
|
||||
long allOrFirstTier;
|
||||
STACK_OF(GENERAL_NAMES) *receiptList;
|
||||
} d;
|
||||
};
|
||||
# endif
|
||||
|
||||
struct CMS_Receipt_st {
|
||||
long version;
|
||||
ASN1_OBJECT *contentType;
|
||||
ASN1_OCTET_STRING *signedContentIdentifier;
|
||||
ASN1_OCTET_STRING *originatorSignatureValue;
|
||||
};
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_SignerInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber)
|
||||
DECLARE_ASN1_ITEM(CMS_Attributes_Sign)
|
||||
DECLARE_ASN1_ITEM(CMS_Attributes_Verify)
|
||||
DECLARE_ASN1_ITEM(CMS_RecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo)
|
||||
DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber)
|
||||
|
||||
# define CMS_SIGNERINFO_ISSUER_SERIAL 0
|
||||
# define CMS_SIGNERINFO_KEYIDENTIFIER 1
|
||||
|
||||
# define CMS_RECIPINFO_ISSUER_SERIAL 0
|
||||
# define CMS_RECIPINFO_KEYIDENTIFIER 1
|
||||
|
||||
# define CMS_REK_ISSUER_SERIAL 0
|
||||
# define CMS_REK_KEYIDENTIFIER 1
|
||||
|
||||
# define CMS_OIK_ISSUER_SERIAL 0
|
||||
# define CMS_OIK_KEYIDENTIFIER 1
|
||||
# define CMS_OIK_PUBKEY 2
|
||||
|
||||
BIO *cms_content_bio(CMS_ContentInfo *cms);
|
||||
|
||||
CMS_ContentInfo *cms_Data_create(void);
|
||||
|
||||
CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md);
|
||||
BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms);
|
||||
int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify);
|
||||
|
||||
BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms);
|
||||
int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain);
|
||||
int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
|
||||
int type);
|
||||
int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer,
|
||||
ASN1_INTEGER **sno);
|
||||
int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert);
|
||||
|
||||
CMS_ContentInfo *cms_CompressedData_create(int comp_nid);
|
||||
BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms);
|
||||
|
||||
void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md);
|
||||
BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm);
|
||||
int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
|
||||
X509_ALGOR *mdalg);
|
||||
|
||||
int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert);
|
||||
int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert);
|
||||
int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert);
|
||||
int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert);
|
||||
|
||||
BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec);
|
||||
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms);
|
||||
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
|
||||
const EVP_CIPHER *cipher,
|
||||
const unsigned char *key, size_t keylen);
|
||||
|
||||
int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
|
||||
int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
|
||||
ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si);
|
||||
|
||||
BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
|
||||
CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms);
|
||||
int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd);
|
||||
int cms_pkey_get_ri_type(EVP_PKEY *pk);
|
||||
/* KARI routines */
|
||||
int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
|
||||
EVP_PKEY *pk, unsigned int flags);
|
||||
int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
|
||||
CMS_RecipientInfo *ri);
|
||||
|
||||
/* PWRI routines */
|
||||
int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
|
||||
int en_de);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
656
cms/lib/cms_lib.c
Normal file
656
cms/lib/cms_lib.c
Normal file
|
@ -0,0 +1,656 @@
|
|||
/* crypto/cms/cms_lib.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo)
|
||||
IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_CertificateChoices)
|
||||
DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice)
|
||||
DECLARE_STACK_OF(CMS_CertificateChoices)
|
||||
DECLARE_STACK_OF(CMS_RevocationInfoChoice)
|
||||
|
||||
const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms)
|
||||
{
|
||||
return cms->contentType;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *cms_Data_create(void)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
cms = CMS_ContentInfo_new();
|
||||
if (cms) {
|
||||
cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
|
||||
/* Never detached */
|
||||
CMS_set_detached(cms, 0);
|
||||
}
|
||||
return cms;
|
||||
}
|
||||
|
||||
BIO *cms_content_bio(CMS_ContentInfo *cms)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
||||
if (!pos)
|
||||
return NULL;
|
||||
/* If content detached data goes nowhere: create NULL BIO */
|
||||
if (!*pos)
|
||||
return BIO_new(BIO_s_null());
|
||||
/*
|
||||
* If content not detached and created return memory BIO
|
||||
*/
|
||||
if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
|
||||
return BIO_new(BIO_s_mem());
|
||||
/* Else content was read in: return read only BIO for it */
|
||||
return BIO_new_mem_buf((*pos)->data, (*pos)->length);
|
||||
}
|
||||
|
||||
BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
|
||||
{
|
||||
BIO *cmsbio, *cont;
|
||||
if (icont)
|
||||
cont = icont;
|
||||
else
|
||||
cont = cms_content_bio(cms);
|
||||
if (!cont) {
|
||||
CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT);
|
||||
return NULL;
|
||||
}
|
||||
switch (OBJ_obj2nid(cms->contentType)) {
|
||||
|
||||
case NID_pkcs7_data:
|
||||
return cont;
|
||||
|
||||
case NID_pkcs7_signed:
|
||||
cmsbio = cms_SignedData_init_bio(cms);
|
||||
break;
|
||||
|
||||
case NID_pkcs7_digest:
|
||||
cmsbio = cms_DigestedData_init_bio(cms);
|
||||
break;
|
||||
#ifdef ZLIB
|
||||
case NID_id_smime_ct_compressedData:
|
||||
cmsbio = cms_CompressedData_init_bio(cms);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case NID_pkcs7_encrypted:
|
||||
cmsbio = cms_EncryptedData_init_bio(cms);
|
||||
break;
|
||||
|
||||
case NID_pkcs7_enveloped:
|
||||
cmsbio = cms_EnvelopedData_init_bio(cms);
|
||||
break;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cmsbio)
|
||||
return BIO_push(cmsbio, cont);
|
||||
|
||||
if (!icont)
|
||||
BIO_free(cont);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
||||
if (!pos)
|
||||
return 0;
|
||||
/* If ebmedded content find memory BIO and set content */
|
||||
if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
|
||||
BIO *mbio;
|
||||
unsigned char *cont;
|
||||
long contlen;
|
||||
mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
|
||||
if (!mbio) {
|
||||
CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
contlen = BIO_get_mem_data(mbio, &cont);
|
||||
/* Set bio as read only so its content can't be clobbered */
|
||||
BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
|
||||
BIO_set_mem_eof_return(mbio, 0);
|
||||
ASN1_STRING_set0(*pos, cont, contlen);
|
||||
(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
|
||||
}
|
||||
|
||||
switch (OBJ_obj2nid(cms->contentType)) {
|
||||
|
||||
case NID_pkcs7_data:
|
||||
case NID_pkcs7_enveloped:
|
||||
case NID_pkcs7_encrypted:
|
||||
case NID_id_smime_ct_compressedData:
|
||||
/* Nothing to do */
|
||||
return 1;
|
||||
|
||||
case NID_pkcs7_signed:
|
||||
return cms_SignedData_final(cms, cmsbio);
|
||||
|
||||
case NID_pkcs7_digest:
|
||||
return cms_DigestedData_do_final(cms, cmsbio, 0);
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an OCTET STRING pointer to content. This allows it to be accessed
|
||||
* or set later.
|
||||
*/
|
||||
|
||||
ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
|
||||
{
|
||||
switch (OBJ_obj2nid(cms->contentType)) {
|
||||
|
||||
case NID_pkcs7_data:
|
||||
return &cms->d.data;
|
||||
|
||||
case NID_pkcs7_signed:
|
||||
return &cms->d.signedData->encapContentInfo->eContent;
|
||||
|
||||
case NID_pkcs7_enveloped:
|
||||
return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
|
||||
|
||||
case NID_pkcs7_digest:
|
||||
return &cms->d.digestedData->encapContentInfo->eContent;
|
||||
|
||||
case NID_pkcs7_encrypted:
|
||||
return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
|
||||
|
||||
case NID_id_smime_ct_authData:
|
||||
return &cms->d.authenticatedData->encapContentInfo->eContent;
|
||||
|
||||
case NID_id_smime_ct_compressedData:
|
||||
return &cms->d.compressedData->encapContentInfo->eContent;
|
||||
|
||||
default:
|
||||
if (cms->d.other->type == V_ASN1_OCTET_STRING)
|
||||
return &cms->d.other->value.octet_string;
|
||||
CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an ASN1_OBJECT pointer to content type. This allows it to be
|
||||
* accessed or set later.
|
||||
*/
|
||||
|
||||
static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
|
||||
{
|
||||
switch (OBJ_obj2nid(cms->contentType)) {
|
||||
|
||||
case NID_pkcs7_signed:
|
||||
return &cms->d.signedData->encapContentInfo->eContentType;
|
||||
|
||||
case NID_pkcs7_enveloped:
|
||||
return &cms->d.envelopedData->encryptedContentInfo->contentType;
|
||||
|
||||
case NID_pkcs7_digest:
|
||||
return &cms->d.digestedData->encapContentInfo->eContentType;
|
||||
|
||||
case NID_pkcs7_encrypted:
|
||||
return &cms->d.encryptedData->encryptedContentInfo->contentType;
|
||||
|
||||
case NID_id_smime_ct_authData:
|
||||
return &cms->d.authenticatedData->encapContentInfo->eContentType;
|
||||
|
||||
case NID_id_smime_ct_compressedData:
|
||||
return &cms->d.compressedData->encapContentInfo->eContentType;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
|
||||
{
|
||||
ASN1_OBJECT **petype;
|
||||
petype = cms_get0_econtent_type(cms);
|
||||
if (petype)
|
||||
return *petype;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
|
||||
{
|
||||
ASN1_OBJECT **petype, *etype;
|
||||
petype = cms_get0_econtent_type(cms);
|
||||
if (!petype)
|
||||
return 0;
|
||||
if (!oid)
|
||||
return 1;
|
||||
etype = OBJ_dup(oid);
|
||||
if (!etype)
|
||||
return 0;
|
||||
ASN1_OBJECT_free(*petype);
|
||||
*petype = etype;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_is_detached(CMS_ContentInfo *cms)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos;
|
||||
pos = CMS_get0_content(cms);
|
||||
if (!pos)
|
||||
return -1;
|
||||
if (*pos)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_set_detached(CMS_ContentInfo *cms, int detached)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos;
|
||||
pos = CMS_get0_content(cms);
|
||||
if (!pos)
|
||||
return 0;
|
||||
if (detached) {
|
||||
if (*pos) {
|
||||
ASN1_OCTET_STRING_free(*pos);
|
||||
*pos = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (!*pos)
|
||||
*pos = ASN1_OCTET_STRING_new();
|
||||
if (*pos) {
|
||||
/*
|
||||
* NB: special flag to show content is created and not read in.
|
||||
*/
|
||||
(*pos)->flags |= ASN1_STRING_FLAG_CONT;
|
||||
return 1;
|
||||
}
|
||||
CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
|
||||
|
||||
void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md)
|
||||
{
|
||||
int param_type;
|
||||
|
||||
if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
param_type = V_ASN1_UNDEF;
|
||||
else
|
||||
param_type = V_ASN1_NULL;
|
||||
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
|
||||
|
||||
}
|
||||
|
||||
/* Create a digest BIO from an X509_ALGOR structure */
|
||||
|
||||
BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
|
||||
{
|
||||
BIO *mdbio = NULL;
|
||||
ASN1_OBJECT *digestoid;
|
||||
const EVP_MD *digest;
|
||||
X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
|
||||
digest = EVP_get_digestbyobj(digestoid);
|
||||
if (!digest) {
|
||||
CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
|
||||
CMS_R_UNKNOWN_DIGEST_ALGORIHM);
|
||||
goto err;
|
||||
}
|
||||
mdbio = BIO_new(BIO_f_md());
|
||||
if (!mdbio || !BIO_set_md(mdbio, digest)) {
|
||||
CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR);
|
||||
goto err;
|
||||
}
|
||||
return mdbio;
|
||||
err:
|
||||
if (mdbio)
|
||||
BIO_free(mdbio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Locate a message digest content from a BIO chain based on SignerInfo */
|
||||
|
||||
int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
|
||||
X509_ALGOR *mdalg)
|
||||
{
|
||||
int nid;
|
||||
ASN1_OBJECT *mdoid;
|
||||
X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
|
||||
nid = OBJ_obj2nid(mdoid);
|
||||
/* Look for digest type to match signature */
|
||||
for (;;) {
|
||||
EVP_MD_CTX *mtmp;
|
||||
chain = BIO_find_type(chain, BIO_TYPE_MD);
|
||||
if (chain == NULL) {
|
||||
CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX,
|
||||
CMS_R_NO_MATCHING_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
BIO_get_md_ctx(chain, &mtmp);
|
||||
if (EVP_MD_CTX_type(mtmp) == nid
|
||||
/*
|
||||
* Workaround for broken implementations that use signature
|
||||
* algorithm OID instead of digest.
|
||||
*/
|
||||
|| EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
|
||||
return EVP_MD_CTX_copy_ex(mctx, mtmp);
|
||||
chain = BIO_next(chain);
|
||||
}
|
||||
}
|
||||
|
||||
static STACK_OF(CMS_CertificateChoices)
|
||||
**cms_get0_certificate_choices(CMS_ContentInfo *cms)
|
||||
{
|
||||
switch (OBJ_obj2nid(cms->contentType)) {
|
||||
|
||||
case NID_pkcs7_signed:
|
||||
return &cms->d.signedData->certificates;
|
||||
|
||||
case NID_pkcs7_enveloped:
|
||||
if (cms->d.envelopedData->originatorInfo == NULL)
|
||||
return NULL;
|
||||
return &cms->d.envelopedData->originatorInfo->certificates;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES,
|
||||
CMS_R_UNSUPPORTED_CONTENT_TYPE);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
|
||||
{
|
||||
STACK_OF(CMS_CertificateChoices) **pcerts;
|
||||
CMS_CertificateChoices *cch;
|
||||
pcerts = cms_get0_certificate_choices(cms);
|
||||
if (!pcerts)
|
||||
return NULL;
|
||||
if (!*pcerts)
|
||||
*pcerts = sk_CMS_CertificateChoices_new_null();
|
||||
if (!*pcerts)
|
||||
return NULL;
|
||||
cch = M_ASN1_new_of(CMS_CertificateChoices);
|
||||
if (!cch)
|
||||
return NULL;
|
||||
if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
|
||||
M_ASN1_free_of(cch, CMS_CertificateChoices);
|
||||
return NULL;
|
||||
}
|
||||
return cch;
|
||||
}
|
||||
|
||||
int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
|
||||
{
|
||||
CMS_CertificateChoices *cch;
|
||||
STACK_OF(CMS_CertificateChoices) **pcerts;
|
||||
int i;
|
||||
pcerts = cms_get0_certificate_choices(cms);
|
||||
if (!pcerts)
|
||||
return 0;
|
||||
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
|
||||
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
|
||||
if (cch->type == CMS_CERTCHOICE_CERT) {
|
||||
if (!X509_cmp(cch->d.certificate, cert)) {
|
||||
CMSerr(CMS_F_CMS_ADD0_CERT,
|
||||
CMS_R_CERTIFICATE_ALREADY_PRESENT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
cch = CMS_add0_CertificateChoices(cms);
|
||||
if (!cch)
|
||||
return 0;
|
||||
cch->type = CMS_CERTCHOICE_CERT;
|
||||
cch->d.certificate = cert;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
|
||||
{
|
||||
int r;
|
||||
r = CMS_add0_cert(cms, cert);
|
||||
if (r > 0)
|
||||
CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
|
||||
return r;
|
||||
}
|
||||
|
||||
static STACK_OF(CMS_RevocationInfoChoice)
|
||||
**cms_get0_revocation_choices(CMS_ContentInfo *cms)
|
||||
{
|
||||
switch (OBJ_obj2nid(cms->contentType)) {
|
||||
|
||||
case NID_pkcs7_signed:
|
||||
return &cms->d.signedData->crls;
|
||||
|
||||
case NID_pkcs7_enveloped:
|
||||
if (cms->d.envelopedData->originatorInfo == NULL)
|
||||
return NULL;
|
||||
return &cms->d.envelopedData->originatorInfo->crls;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES,
|
||||
CMS_R_UNSUPPORTED_CONTENT_TYPE);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
|
||||
{
|
||||
STACK_OF(CMS_RevocationInfoChoice) **pcrls;
|
||||
CMS_RevocationInfoChoice *rch;
|
||||
pcrls = cms_get0_revocation_choices(cms);
|
||||
if (!pcrls)
|
||||
return NULL;
|
||||
if (!*pcrls)
|
||||
*pcrls = sk_CMS_RevocationInfoChoice_new_null();
|
||||
if (!*pcrls)
|
||||
return NULL;
|
||||
rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
|
||||
if (!rch)
|
||||
return NULL;
|
||||
if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
|
||||
M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
|
||||
return NULL;
|
||||
}
|
||||
return rch;
|
||||
}
|
||||
|
||||
int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
|
||||
{
|
||||
CMS_RevocationInfoChoice *rch;
|
||||
rch = CMS_add0_RevocationInfoChoice(cms);
|
||||
if (!rch)
|
||||
return 0;
|
||||
rch->type = CMS_REVCHOICE_CRL;
|
||||
rch->d.crl = crl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
|
||||
{
|
||||
int r;
|
||||
r = CMS_add0_crl(cms, crl);
|
||||
if (r > 0)
|
||||
CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
|
||||
return r;
|
||||
}
|
||||
|
||||
STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
|
||||
{
|
||||
STACK_OF(X509) *certs = NULL;
|
||||
CMS_CertificateChoices *cch;
|
||||
STACK_OF(CMS_CertificateChoices) **pcerts;
|
||||
int i;
|
||||
pcerts = cms_get0_certificate_choices(cms);
|
||||
if (!pcerts)
|
||||
return NULL;
|
||||
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
|
||||
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
|
||||
if (cch->type == 0) {
|
||||
if (!certs) {
|
||||
certs = sk_X509_new_null();
|
||||
if (!certs)
|
||||
return NULL;
|
||||
}
|
||||
if (!sk_X509_push(certs, cch->d.certificate)) {
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
return NULL;
|
||||
}
|
||||
CRYPTO_add(&cch->d.certificate->references, 1, CRYPTO_LOCK_X509);
|
||||
}
|
||||
}
|
||||
return certs;
|
||||
|
||||
}
|
||||
|
||||
STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
|
||||
{
|
||||
STACK_OF(X509_CRL) *crls = NULL;
|
||||
STACK_OF(CMS_RevocationInfoChoice) **pcrls;
|
||||
CMS_RevocationInfoChoice *rch;
|
||||
int i;
|
||||
pcrls = cms_get0_revocation_choices(cms);
|
||||
if (!pcrls)
|
||||
return NULL;
|
||||
for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
|
||||
rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
|
||||
if (rch->type == 0) {
|
||||
if (!crls) {
|
||||
crls = sk_X509_CRL_new_null();
|
||||
if (!crls)
|
||||
return NULL;
|
||||
}
|
||||
if (!sk_X509_CRL_push(crls, rch->d.crl)) {
|
||||
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
||||
return NULL;
|
||||
}
|
||||
CRYPTO_add(&rch->d.crl->references, 1, CRYPTO_LOCK_X509_CRL);
|
||||
}
|
||||
}
|
||||
return crls;
|
||||
}
|
||||
|
||||
int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
|
||||
{
|
||||
int ret;
|
||||
ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
|
||||
if (ret)
|
||||
return ret;
|
||||
return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert));
|
||||
}
|
||||
|
||||
int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
|
||||
{
|
||||
X509_check_purpose(cert, -1, -1);
|
||||
if (!cert->skid)
|
||||
return -1;
|
||||
return ASN1_OCTET_STRING_cmp(keyid, cert->skid);
|
||||
}
|
||||
|
||||
int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
|
||||
{
|
||||
CMS_IssuerAndSerialNumber *ias;
|
||||
ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber);
|
||||
if (!ias)
|
||||
goto err;
|
||||
if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
|
||||
goto err;
|
||||
if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert)))
|
||||
goto err;
|
||||
if (*pias)
|
||||
M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber);
|
||||
*pias = ias;
|
||||
return 1;
|
||||
err:
|
||||
if (ias)
|
||||
M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber);
|
||||
CMSerr(CMS_F_CMS_SET1_IAS, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
|
||||
{
|
||||
ASN1_OCTET_STRING *keyid = NULL;
|
||||
X509_check_purpose(cert, -1, -1);
|
||||
if (!cert->skid) {
|
||||
CMSerr(CMS_F_CMS_SET1_KEYID, CMS_R_CERTIFICATE_HAS_NO_KEYID);
|
||||
return 0;
|
||||
}
|
||||
keyid = ASN1_STRING_dup(cert->skid);
|
||||
if (!keyid) {
|
||||
CMSerr(CMS_F_CMS_SET1_KEYID, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (*pkeyid)
|
||||
ASN1_OCTET_STRING_free(*pkeyid);
|
||||
*pkeyid = keyid;
|
||||
return 1;
|
||||
}
|
435
cms/lib/cms_pwri.c
Normal file
435
cms/lib/cms_pwri.c
Normal file
|
@ -0,0 +1,435 @@
|
|||
/* crypto/cms/cms_pwri.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2009 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/aes.h>
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
|
||||
unsigned char *pass, ossl_ssize_t passlen)
|
||||
{
|
||||
CMS_PasswordRecipientInfo *pwri;
|
||||
if (ri->type != CMS_RECIPINFO_PASS) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pwri = ri->d.pwri;
|
||||
pwri->pass = pass;
|
||||
if (pass && passlen < 0)
|
||||
passlen = strlen((char *)pass);
|
||||
pwri->passlen = passlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
|
||||
int iter, int wrap_nid,
|
||||
int pbe_nid,
|
||||
unsigned char *pass,
|
||||
ossl_ssize_t passlen,
|
||||
const EVP_CIPHER *kekciph)
|
||||
{
|
||||
CMS_RecipientInfo *ri = NULL;
|
||||
CMS_EnvelopedData *env;
|
||||
CMS_PasswordRecipientInfo *pwri;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
X509_ALGOR *encalg = NULL;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
int ivlen;
|
||||
|
||||
env = cms_get0_enveloped(cms);
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
if (wrap_nid <= 0)
|
||||
wrap_nid = NID_id_alg_PWRI_KEK;
|
||||
|
||||
if (pbe_nid <= 0)
|
||||
pbe_nid = NID_id_pbkdf2;
|
||||
|
||||
/* Get from enveloped data */
|
||||
if (kekciph == NULL)
|
||||
kekciph = env->encryptedContentInfo->cipher;
|
||||
|
||||
if (kekciph == NULL) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER);
|
||||
return NULL;
|
||||
}
|
||||
if (wrap_nid != NID_id_alg_PWRI_KEK) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
|
||||
CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Setup algorithm identifier for cipher */
|
||||
encalg = X509_ALGOR_new();
|
||||
if (encalg == NULL) {
|
||||
goto merr;
|
||||
}
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
|
||||
if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
|
||||
|
||||
if (ivlen > 0) {
|
||||
if (RAND_bytes(iv, ivlen) <= 0)
|
||||
goto err;
|
||||
if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
encalg->parameter = ASN1_TYPE_new();
|
||||
if (!encalg->parameter) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0) {
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
|
||||
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx));
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
/* Initialize recipient info */
|
||||
ri = M_ASN1_new_of(CMS_RecipientInfo);
|
||||
if (!ri)
|
||||
goto merr;
|
||||
|
||||
ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
|
||||
if (!ri->d.pwri)
|
||||
goto merr;
|
||||
ri->type = CMS_RECIPINFO_PASS;
|
||||
|
||||
pwri = ri->d.pwri;
|
||||
/* Since this is overwritten, free up empty structure already there */
|
||||
X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
|
||||
pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
|
||||
if (!pwri->keyEncryptionAlgorithm)
|
||||
goto merr;
|
||||
pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
|
||||
pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
|
||||
if (!pwri->keyEncryptionAlgorithm->parameter)
|
||||
goto merr;
|
||||
|
||||
if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR),
|
||||
&pwri->keyEncryptionAlgorithm->parameter->
|
||||
value.sequence))
|
||||
goto merr;
|
||||
pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
|
||||
|
||||
X509_ALGOR_free(encalg);
|
||||
encalg = NULL;
|
||||
|
||||
/* Setup PBE algorithm */
|
||||
|
||||
pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
|
||||
|
||||
if (!pwri->keyDerivationAlgorithm)
|
||||
goto err;
|
||||
|
||||
CMS_RecipientInfo_set0_password(ri, pass, passlen);
|
||||
pwri->version = 0;
|
||||
|
||||
if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
|
||||
goto merr;
|
||||
|
||||
return ri;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
if (ri)
|
||||
M_ASN1_free_of(ri, CMS_RecipientInfo);
|
||||
if (encalg)
|
||||
X509_ALGOR_free(encalg);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an implementation of the key wrapping mechanism in RFC3211, at
|
||||
* some point this should go into EVP.
|
||||
*/
|
||||
|
||||
static int kek_unwrap_key(unsigned char *out, size_t *outlen,
|
||||
const unsigned char *in, size_t inlen,
|
||||
EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
|
||||
unsigned char *tmp;
|
||||
int outl, rv = 0;
|
||||
if (inlen < 2 * blocklen) {
|
||||
/* too small */
|
||||
return 0;
|
||||
}
|
||||
if (inlen % blocklen) {
|
||||
/* Invalid size */
|
||||
return 0;
|
||||
}
|
||||
tmp = OPENSSL_malloc(inlen);
|
||||
if (!tmp)
|
||||
return 0;
|
||||
/* setup IV by decrypting last two blocks */
|
||||
EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
|
||||
in + inlen - 2 * blocklen, blocklen * 2);
|
||||
/*
|
||||
* Do a decrypt of last decrypted block to set IV to correct value output
|
||||
* it to start of buffer so we don't corrupt decrypted block this works
|
||||
* because buffer is at least two block lengths long.
|
||||
*/
|
||||
EVP_DecryptUpdate(ctx, tmp, &outl, tmp + inlen - blocklen, blocklen);
|
||||
/* Can now decrypt first n - 1 blocks */
|
||||
EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen);
|
||||
|
||||
/* Reset IV to original value */
|
||||
EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL);
|
||||
/* Decrypt again */
|
||||
EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen);
|
||||
/* Check check bytes */
|
||||
if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) {
|
||||
/* Check byte failure */
|
||||
goto err;
|
||||
}
|
||||
if (inlen < (size_t)(tmp[0] - 4)) {
|
||||
/* Invalid length value */
|
||||
goto err;
|
||||
}
|
||||
*outlen = (size_t)tmp[0];
|
||||
memcpy(out, tmp + 4, *outlen);
|
||||
rv = 1;
|
||||
err:
|
||||
OPENSSL_cleanse(tmp, inlen);
|
||||
OPENSSL_free(tmp);
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
static int kek_wrap_key(unsigned char *out, size_t *outlen,
|
||||
const unsigned char *in, size_t inlen,
|
||||
EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
|
||||
size_t olen;
|
||||
int dummy;
|
||||
/*
|
||||
* First decide length of output buffer: need header and round up to
|
||||
* multiple of block length.
|
||||
*/
|
||||
olen = (inlen + 4 + blocklen - 1) / blocklen;
|
||||
olen *= blocklen;
|
||||
if (olen < 2 * blocklen) {
|
||||
/* Key too small */
|
||||
return 0;
|
||||
}
|
||||
if (inlen > 0xFF) {
|
||||
/* Key too large */
|
||||
return 0;
|
||||
}
|
||||
if (out) {
|
||||
/* Set header */
|
||||
out[0] = (unsigned char)inlen;
|
||||
out[1] = in[0] ^ 0xFF;
|
||||
out[2] = in[1] ^ 0xFF;
|
||||
out[3] = in[2] ^ 0xFF;
|
||||
memcpy(out + 4, in, inlen);
|
||||
/* Add random padding to end */
|
||||
if (olen > inlen + 4
|
||||
&& RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0)
|
||||
return 0;
|
||||
/* Encrypt twice */
|
||||
EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
|
||||
EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
|
||||
}
|
||||
|
||||
*outlen = olen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Encrypt/Decrypt content key in PWRI recipient info */
|
||||
|
||||
int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
|
||||
int en_de)
|
||||
{
|
||||
CMS_EncryptedContentInfo *ec;
|
||||
CMS_PasswordRecipientInfo *pwri;
|
||||
const unsigned char *p = NULL;
|
||||
int plen;
|
||||
int r = 0;
|
||||
X509_ALGOR *algtmp, *kekalg = NULL;
|
||||
EVP_CIPHER_CTX kekctx;
|
||||
const EVP_CIPHER *kekcipher;
|
||||
unsigned char *key = NULL;
|
||||
size_t keylen;
|
||||
|
||||
ec = cms->d.envelopedData->encryptedContentInfo;
|
||||
|
||||
pwri = ri->d.pwri;
|
||||
EVP_CIPHER_CTX_init(&kekctx);
|
||||
|
||||
if (!pwri->pass) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
|
||||
return 0;
|
||||
}
|
||||
algtmp = pwri->keyEncryptionAlgorithm;
|
||||
|
||||
if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
|
||||
CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (algtmp->parameter->type == V_ASN1_SEQUENCE) {
|
||||
p = algtmp->parameter->value.sequence->data;
|
||||
plen = algtmp->parameter->value.sequence->length;
|
||||
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
|
||||
}
|
||||
if (kekalg == NULL) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
|
||||
CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
|
||||
|
||||
if (!kekcipher) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Fixup cipher based on AlgorithmIdentifier to set IV etc */
|
||||
if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de))
|
||||
goto err;
|
||||
EVP_CIPHER_CTX_set_padding(&kekctx, 0);
|
||||
if (EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
|
||||
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
algtmp = pwri->keyDerivationAlgorithm;
|
||||
|
||||
/* Finish password based key derivation to setup key in "ctx" */
|
||||
|
||||
if (EVP_PBE_CipherInit(algtmp->algorithm,
|
||||
(char *)pwri->pass, pwri->passlen,
|
||||
algtmp->parameter, &kekctx, en_de) < 0) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Finally wrap/unwrap the key */
|
||||
|
||||
if (en_de) {
|
||||
|
||||
if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx))
|
||||
goto err;
|
||||
|
||||
key = OPENSSL_malloc(keylen);
|
||||
|
||||
if (!key)
|
||||
goto err;
|
||||
|
||||
if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx))
|
||||
goto err;
|
||||
pwri->encryptedKey->data = key;
|
||||
pwri->encryptedKey->length = keylen;
|
||||
} else {
|
||||
key = OPENSSL_malloc(pwri->encryptedKey->length);
|
||||
|
||||
if (!key) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!kek_unwrap_key(key, &keylen,
|
||||
pwri->encryptedKey->data,
|
||||
pwri->encryptedKey->length, &kekctx)) {
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ec->key = key;
|
||||
ec->keylen = keylen;
|
||||
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&kekctx);
|
||||
|
||||
if (!r && key)
|
||||
OPENSSL_free(key);
|
||||
X509_ALGOR_free(kekalg);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
960
cms/lib/cms_sd.c
Normal file
960
cms/lib/cms_sd.c
Normal file
|
@ -0,0 +1,960 @@
|
|||
/* crypto/cms/cms_sd.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
extern int libressl_pkey_ctrl(EVP_PKEY *, int, long, void *);
|
||||
extern int libressl_pkey_ctx_ctrl(EVP_PKEY_CTX *, int, int, int, int, void *);
|
||||
|
||||
/* CMS SignedData Utilities */
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_SignedData)
|
||||
|
||||
static CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms)
|
||||
{
|
||||
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) {
|
||||
CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
|
||||
return NULL;
|
||||
}
|
||||
return cms->d.signedData;
|
||||
}
|
||||
|
||||
static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
|
||||
{
|
||||
if (cms->d.other == NULL) {
|
||||
cms->d.signedData = M_ASN1_new_of(CMS_SignedData);
|
||||
if (!cms->d.signedData) {
|
||||
CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
cms->d.signedData->version = 1;
|
||||
cms->d.signedData->encapContentInfo->eContentType =
|
||||
OBJ_nid2obj(NID_pkcs7_data);
|
||||
cms->d.signedData->encapContentInfo->partial = 1;
|
||||
ASN1_OBJECT_free(cms->contentType);
|
||||
cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
|
||||
return cms->d.signedData;
|
||||
}
|
||||
return cms_get0_signed(cms);
|
||||
}
|
||||
|
||||
/* Just initialize SignedData e.g. for certs only structure */
|
||||
|
||||
int CMS_SignedData_init(CMS_ContentInfo *cms)
|
||||
{
|
||||
if (cms_signed_data_init(cms))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check structures and fixup version numbers (if necessary) */
|
||||
|
||||
static void cms_sd_set_version(CMS_SignedData *sd)
|
||||
{
|
||||
int i;
|
||||
CMS_CertificateChoices *cch;
|
||||
CMS_RevocationInfoChoice *rch;
|
||||
CMS_SignerInfo *si;
|
||||
|
||||
for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) {
|
||||
cch = sk_CMS_CertificateChoices_value(sd->certificates, i);
|
||||
if (cch->type == CMS_CERTCHOICE_OTHER) {
|
||||
if (sd->version < 5)
|
||||
sd->version = 5;
|
||||
} else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
|
||||
if (sd->version < 4)
|
||||
sd->version = 4;
|
||||
} else if (cch->type == CMS_CERTCHOICE_V1ACERT) {
|
||||
if (sd->version < 3)
|
||||
sd->version = 3;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) {
|
||||
rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i);
|
||||
if (rch->type == CMS_REVCHOICE_OTHER) {
|
||||
if (sd->version < 5)
|
||||
sd->version = 5;
|
||||
}
|
||||
}
|
||||
|
||||
if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data)
|
||||
&& (sd->version < 3))
|
||||
sd->version = 3;
|
||||
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
|
||||
if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
|
||||
if (si->version < 3)
|
||||
si->version = 3;
|
||||
if (sd->version < 3)
|
||||
sd->version = 3;
|
||||
} else if (si->version < 1)
|
||||
si->version = 1;
|
||||
}
|
||||
|
||||
if (sd->version < 1)
|
||||
sd->version = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Copy an existing messageDigest value */
|
||||
|
||||
static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
|
||||
{
|
||||
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||
CMS_SignerInfo *sitmp;
|
||||
int i;
|
||||
sinfos = CMS_get0_SignerInfos(cms);
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
ASN1_OCTET_STRING *messageDigest;
|
||||
sitmp = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (sitmp == si)
|
||||
continue;
|
||||
if (CMS_signed_get_attr_count(sitmp) < 0)
|
||||
continue;
|
||||
if (OBJ_cmp(si->digestAlgorithm->algorithm,
|
||||
sitmp->digestAlgorithm->algorithm))
|
||||
continue;
|
||||
messageDigest = CMS_signed_get0_data_by_OBJ(sitmp,
|
||||
OBJ_nid2obj
|
||||
(NID_pkcs9_messageDigest),
|
||||
-3, V_ASN1_OCTET_STRING);
|
||||
if (!messageDigest) {
|
||||
CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST,
|
||||
CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
|
||||
V_ASN1_OCTET_STRING,
|
||||
messageDigest, -1))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
|
||||
{
|
||||
switch (type) {
|
||||
case CMS_SIGNERINFO_ISSUER_SERIAL:
|
||||
if (!cms_set1_ias(&sid->d.issuerAndSerialNumber, cert))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case CMS_SIGNERINFO_KEYIDENTIFIER:
|
||||
if (!cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sid->type = type;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer,
|
||||
ASN1_INTEGER **sno)
|
||||
{
|
||||
if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) {
|
||||
if (issuer)
|
||||
*issuer = sid->d.issuerAndSerialNumber->issuer;
|
||||
if (sno)
|
||||
*sno = sid->d.issuerAndSerialNumber->serialNumber;
|
||||
} else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
|
||||
if (keyid)
|
||||
*keyid = sid->d.subjectKeyIdentifier;
|
||||
} else
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
|
||||
{
|
||||
if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
|
||||
return cms_ias_cert_cmp(sid->d.issuerAndSerialNumber, cert);
|
||||
else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
|
||||
return cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
|
||||
{
|
||||
EVP_PKEY *pkey = si->pkey;
|
||||
int i;
|
||||
if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
|
||||
return 1;
|
||||
i = libressl_pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
|
||||
if (i == -2) {
|
||||
CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
return 0;
|
||||
}
|
||||
if (i <= 0) {
|
||||
CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_CTRL_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
|
||||
X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
|
||||
unsigned int flags)
|
||||
{
|
||||
CMS_SignedData *sd;
|
||||
CMS_SignerInfo *si = NULL;
|
||||
X509_ALGOR *alg;
|
||||
int i, type;
|
||||
if (!X509_check_private_key(signer, pk)) {
|
||||
CMSerr(CMS_F_CMS_ADD1_SIGNER,
|
||||
CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
|
||||
return NULL;
|
||||
}
|
||||
sd = cms_signed_data_init(cms);
|
||||
if (!sd)
|
||||
goto err;
|
||||
si = M_ASN1_new_of(CMS_SignerInfo);
|
||||
if (!si)
|
||||
goto merr;
|
||||
X509_check_purpose(signer, -1, -1);
|
||||
|
||||
CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
|
||||
CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
|
||||
|
||||
si->pkey = pk;
|
||||
si->signer = signer;
|
||||
EVP_MD_CTX_init(&si->mctx);
|
||||
si->pctx = NULL;
|
||||
|
||||
if (flags & CMS_USE_KEYID) {
|
||||
si->version = 3;
|
||||
if (sd->version < 3)
|
||||
sd->version = 3;
|
||||
type = CMS_SIGNERINFO_KEYIDENTIFIER;
|
||||
} else {
|
||||
type = CMS_SIGNERINFO_ISSUER_SERIAL;
|
||||
si->version = 1;
|
||||
}
|
||||
|
||||
if (!cms_set1_SignerIdentifier(si->sid, signer, type))
|
||||
goto err;
|
||||
|
||||
if (md == NULL) {
|
||||
int def_nid;
|
||||
if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
|
||||
goto err;
|
||||
md = EVP_get_digestbynid(def_nid);
|
||||
if (md == NULL) {
|
||||
CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!md) {
|
||||
CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET);
|
||||
goto err;
|
||||
}
|
||||
|
||||
cms_DigestAlgorithm_set(si->digestAlgorithm, md);
|
||||
|
||||
/* See if digest is present in digestAlgorithms */
|
||||
for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
|
||||
ASN1_OBJECT *aoid;
|
||||
alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
|
||||
X509_ALGOR_get0(&aoid, NULL, NULL, alg);
|
||||
if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) {
|
||||
alg = X509_ALGOR_new();
|
||||
if (!alg)
|
||||
goto merr;
|
||||
cms_DigestAlgorithm_set(alg, md);
|
||||
if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) {
|
||||
X509_ALGOR_free(alg);
|
||||
goto merr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
|
||||
goto err;
|
||||
if (!(flags & CMS_NOATTR)) {
|
||||
/*
|
||||
* Initialialize signed attributes strutucture so other attributes
|
||||
* such as signing time etc are added later even if we add none here.
|
||||
*/
|
||||
if (!si->signedAttrs) {
|
||||
si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
|
||||
if (!si->signedAttrs)
|
||||
goto merr;
|
||||
}
|
||||
|
||||
if (!(flags & CMS_NOSMIMECAP)) {
|
||||
STACK_OF(X509_ALGOR) *smcap = NULL;
|
||||
i = CMS_add_standard_smimecap(&smcap);
|
||||
if (i)
|
||||
i = CMS_add_smimecap(si, smcap);
|
||||
sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
|
||||
if (!i)
|
||||
goto merr;
|
||||
}
|
||||
if (flags & CMS_REUSE_DIGEST) {
|
||||
if (!cms_copy_messageDigest(cms, si))
|
||||
goto err;
|
||||
if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) &&
|
||||
!CMS_SignerInfo_sign(si))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & CMS_NOCERTS)) {
|
||||
/* NB ignore -1 return for duplicate cert */
|
||||
if (!CMS_add1_cert(cms, signer))
|
||||
goto merr;
|
||||
}
|
||||
|
||||
if (flags & CMS_KEY_PARAM) {
|
||||
if (flags & CMS_NOATTR) {
|
||||
si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL);
|
||||
if (!si->pctx)
|
||||
goto err;
|
||||
if (EVP_PKEY_sign_init(si->pctx) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
|
||||
goto err;
|
||||
} else if (EVP_DigestSignInit(&si->mctx, &si->pctx, md, NULL, pk) <=
|
||||
0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!sd->signerInfos)
|
||||
sd->signerInfos = sk_CMS_SignerInfo_new_null();
|
||||
if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si))
|
||||
goto merr;
|
||||
|
||||
return si;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
if (si)
|
||||
M_ASN1_free_of(si, CMS_SignerInfo);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
|
||||
{
|
||||
ASN1_TIME *tt;
|
||||
int r = 0;
|
||||
if (t)
|
||||
tt = t;
|
||||
else
|
||||
tt = X509_gmtime_adj(NULL, 0);
|
||||
|
||||
if (!tt)
|
||||
goto merr;
|
||||
|
||||
if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
|
||||
tt->type, tt, -1) <= 0)
|
||||
goto merr;
|
||||
|
||||
r = 1;
|
||||
|
||||
merr:
|
||||
|
||||
if (!t)
|
||||
ASN1_TIME_free(tt);
|
||||
|
||||
if (!r)
|
||||
CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si)
|
||||
{
|
||||
return si->pctx;
|
||||
}
|
||||
|
||||
EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
|
||||
{
|
||||
return &si->mctx;
|
||||
}
|
||||
|
||||
STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
|
||||
{
|
||||
CMS_SignedData *sd;
|
||||
sd = cms_get0_signed(cms);
|
||||
if (!sd)
|
||||
return NULL;
|
||||
return sd->signerInfos;
|
||||
}
|
||||
|
||||
STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
|
||||
{
|
||||
STACK_OF(X509) *signers = NULL;
|
||||
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||
CMS_SignerInfo *si;
|
||||
int i;
|
||||
sinfos = CMS_get0_SignerInfos(cms);
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (si->signer) {
|
||||
if (!signers) {
|
||||
signers = sk_X509_new_null();
|
||||
if (!signers)
|
||||
return NULL;
|
||||
}
|
||||
if (!sk_X509_push(signers, si->signer)) {
|
||||
sk_X509_free(signers);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return signers;
|
||||
}
|
||||
|
||||
void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
|
||||
{
|
||||
if (signer) {
|
||||
CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
|
||||
if (si->pkey)
|
||||
EVP_PKEY_free(si->pkey);
|
||||
si->pkey = X509_get_pubkey(signer);
|
||||
}
|
||||
if (si->signer)
|
||||
X509_free(si->signer);
|
||||
si->signer = signer;
|
||||
}
|
||||
|
||||
int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
|
||||
ASN1_OCTET_STRING **keyid,
|
||||
X509_NAME **issuer, ASN1_INTEGER **sno)
|
||||
{
|
||||
return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
|
||||
}
|
||||
|
||||
int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
|
||||
{
|
||||
return cms_SignerIdentifier_cert_cmp(si->sid, cert);
|
||||
}
|
||||
|
||||
int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
|
||||
unsigned int flags)
|
||||
{
|
||||
CMS_SignedData *sd;
|
||||
CMS_SignerInfo *si;
|
||||
CMS_CertificateChoices *cch;
|
||||
STACK_OF(CMS_CertificateChoices) *certs;
|
||||
X509 *x;
|
||||
int i, j;
|
||||
int ret = 0;
|
||||
sd = cms_get0_signed(cms);
|
||||
if (!sd)
|
||||
return -1;
|
||||
certs = sd->certificates;
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
|
||||
if (si->signer)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < sk_X509_num(scerts); j++) {
|
||||
x = sk_X509_value(scerts, j);
|
||||
if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
|
||||
CMS_SignerInfo_set1_signer_cert(si, x);
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (si->signer || (flags & CMS_NOINTERN))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
|
||||
cch = sk_CMS_CertificateChoices_value(certs, j);
|
||||
if (cch->type != 0)
|
||||
continue;
|
||||
x = cch->d.certificate;
|
||||
if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
|
||||
CMS_SignerInfo_set1_signer_cert(si, x);
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
|
||||
X509 **signer, X509_ALGOR **pdig,
|
||||
X509_ALGOR **psig)
|
||||
{
|
||||
if (pk)
|
||||
*pk = si->pkey;
|
||||
if (signer)
|
||||
*signer = si->signer;
|
||||
if (pdig)
|
||||
*pdig = si->digestAlgorithm;
|
||||
if (psig)
|
||||
*psig = si->signatureAlgorithm;
|
||||
}
|
||||
|
||||
ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si)
|
||||
{
|
||||
return si->signature;
|
||||
}
|
||||
|
||||
static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
|
||||
CMS_SignerInfo *si, BIO *chain)
|
||||
{
|
||||
EVP_MD_CTX mctx;
|
||||
int r = 0;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_MD_CTX_init(&mctx);
|
||||
|
||||
if (!si->pkey) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
|
||||
goto err;
|
||||
/* Set SignerInfo algortihm details if we used custom parametsr */
|
||||
if (si->pctx && !cms_sd_asn1_ctrl(si, 0))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If any signed attributes calculate and add messageDigest attribute
|
||||
*/
|
||||
|
||||
if (CMS_signed_get_attr_count(si) >= 0) {
|
||||
ASN1_OBJECT *ctype =
|
||||
cms->d.signedData->encapContentInfo->eContentType;
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
unsigned int mdlen;
|
||||
if (!EVP_DigestFinal_ex(&mctx, md, &mdlen))
|
||||
goto err;
|
||||
if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
|
||||
V_ASN1_OCTET_STRING, md, mdlen))
|
||||
goto err;
|
||||
/* Copy content type across */
|
||||
if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
|
||||
V_ASN1_OBJECT, ctype, -1) <= 0)
|
||||
goto err;
|
||||
if (!CMS_SignerInfo_sign(si))
|
||||
goto err;
|
||||
} else if (si->pctx) {
|
||||
unsigned char *sig;
|
||||
size_t siglen;
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
unsigned int mdlen;
|
||||
pctx = si->pctx;
|
||||
if (!EVP_DigestFinal_ex(&mctx, md, &mdlen))
|
||||
goto err;
|
||||
siglen = EVP_PKEY_size(si->pkey);
|
||||
sig = OPENSSL_malloc(siglen);
|
||||
if (!sig) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0)
|
||||
goto err;
|
||||
ASN1_STRING_set0(si->signature, sig, siglen);
|
||||
} else {
|
||||
unsigned char *sig;
|
||||
unsigned int siglen;
|
||||
sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey));
|
||||
if (!sig) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_SignFinal(&mctx, sig, &siglen, si->pkey)) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_SIGNFINAL_ERROR);
|
||||
OPENSSL_free(sig);
|
||||
goto err;
|
||||
}
|
||||
ASN1_STRING_set0(si->signature, sig, siglen);
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_cleanup(&mctx);
|
||||
if (pctx)
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
|
||||
{
|
||||
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||
CMS_SignerInfo *si;
|
||||
int i;
|
||||
sinfos = CMS_get0_SignerInfos(cms);
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (!cms_SignerInfo_content_sign(cms, si, chain))
|
||||
return 0;
|
||||
}
|
||||
cms->d.signedData->encapContentInfo->partial = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_SignerInfo_sign(CMS_SignerInfo *si)
|
||||
{
|
||||
EVP_MD_CTX *mctx = &si->mctx;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
unsigned char *abuf = NULL;
|
||||
int alen;
|
||||
size_t siglen;
|
||||
const EVP_MD *md = NULL;
|
||||
|
||||
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
|
||||
if (md == NULL)
|
||||
return 0;
|
||||
|
||||
if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
|
||||
if (!cms_add1_signingTime(si, NULL))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (si->pctx)
|
||||
pctx = si->pctx;
|
||||
else {
|
||||
EVP_MD_CTX_init(mctx);
|
||||
if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (libressl_pkey_ctx_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
|
||||
EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
|
||||
ASN1_ITEM_rptr(CMS_Attributes_Sign));
|
||||
if (!abuf)
|
||||
goto err;
|
||||
if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
|
||||
goto err;
|
||||
if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
|
||||
goto err;
|
||||
OPENSSL_free(abuf);
|
||||
abuf = OPENSSL_malloc(siglen);
|
||||
if (!abuf)
|
||||
goto err;
|
||||
if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
|
||||
goto err;
|
||||
|
||||
if (libressl_pkey_ctx_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
|
||||
EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_cleanup(mctx);
|
||||
|
||||
ASN1_STRING_set0(si->signature, abuf, siglen);
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
if (abuf)
|
||||
OPENSSL_free(abuf);
|
||||
EVP_MD_CTX_cleanup(mctx);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int CMS_SignerInfo_verify(CMS_SignerInfo *si)
|
||||
{
|
||||
EVP_MD_CTX *mctx = &si->mctx;
|
||||
unsigned char *abuf = NULL;
|
||||
int alen, r = -1;
|
||||
const EVP_MD *md = NULL;
|
||||
|
||||
if (!si->pkey) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY);
|
||||
return -1;
|
||||
}
|
||||
|
||||
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
|
||||
if (md == NULL)
|
||||
return -1;
|
||||
EVP_MD_CTX_init(mctx);
|
||||
if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0)
|
||||
goto err;
|
||||
|
||||
if (!cms_sd_asn1_ctrl(si, 1))
|
||||
goto err;
|
||||
|
||||
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
|
||||
ASN1_ITEM_rptr(CMS_Attributes_Verify));
|
||||
if (!abuf)
|
||||
goto err;
|
||||
r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
|
||||
OPENSSL_free(abuf);
|
||||
if (r <= 0) {
|
||||
r = -1;
|
||||
goto err;
|
||||
}
|
||||
r = EVP_DigestVerifyFinal(mctx,
|
||||
si->signature->data, si->signature->length);
|
||||
if (r <= 0)
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
|
||||
err:
|
||||
EVP_MD_CTX_cleanup(mctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Create a chain of digest BIOs from a CMS ContentInfo */
|
||||
|
||||
BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
|
||||
{
|
||||
int i;
|
||||
CMS_SignedData *sd;
|
||||
BIO *chain = NULL;
|
||||
sd = cms_get0_signed(cms);
|
||||
if (!sd)
|
||||
return NULL;
|
||||
if (cms->d.signedData->encapContentInfo->partial)
|
||||
cms_sd_set_version(sd);
|
||||
for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
|
||||
X509_ALGOR *digestAlgorithm;
|
||||
BIO *mdbio;
|
||||
digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
|
||||
mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm);
|
||||
if (!mdbio)
|
||||
goto err;
|
||||
if (chain)
|
||||
BIO_push(chain, mdbio);
|
||||
else
|
||||
chain = mdbio;
|
||||
}
|
||||
return chain;
|
||||
err:
|
||||
if (chain)
|
||||
BIO_free_all(chain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
|
||||
{
|
||||
ASN1_OCTET_STRING *os = NULL;
|
||||
EVP_MD_CTX mctx;
|
||||
EVP_PKEY_CTX *pkctx = NULL;
|
||||
int r = -1;
|
||||
unsigned char mval[EVP_MAX_MD_SIZE];
|
||||
unsigned int mlen;
|
||||
EVP_MD_CTX_init(&mctx);
|
||||
/* If we have any signed attributes look for messageDigest value */
|
||||
if (CMS_signed_get_attr_count(si) >= 0) {
|
||||
os = CMS_signed_get0_data_by_OBJ(si,
|
||||
OBJ_nid2obj(NID_pkcs9_messageDigest),
|
||||
-3, V_ASN1_OCTET_STRING);
|
||||
if (!os) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
|
||||
CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
|
||||
goto err;
|
||||
|
||||
if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
|
||||
CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If messageDigest found compare it */
|
||||
|
||||
if (os) {
|
||||
if (mlen != (unsigned int)os->length) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
|
||||
CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(mval, os->data, mlen)) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
|
||||
CMS_R_VERIFICATION_FAILURE);
|
||||
r = 0;
|
||||
} else
|
||||
r = 1;
|
||||
} else {
|
||||
const EVP_MD *md = EVP_MD_CTX_md(&mctx);
|
||||
pkctx = EVP_PKEY_CTX_new(si->pkey, NULL);
|
||||
if (pkctx == NULL)
|
||||
goto err;
|
||||
if (EVP_PKEY_verify_init(pkctx) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
|
||||
goto err;
|
||||
si->pctx = pkctx;
|
||||
if (!cms_sd_asn1_ctrl(si, 1))
|
||||
goto err;
|
||||
r = EVP_PKEY_verify(pkctx, si->signature->data,
|
||||
si->signature->length, mval, mlen);
|
||||
if (r <= 0) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
|
||||
CMS_R_VERIFICATION_FAILURE);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
if (pkctx)
|
||||
EVP_PKEY_CTX_free(pkctx);
|
||||
EVP_MD_CTX_cleanup(&mctx);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
|
||||
{
|
||||
unsigned char *smder = NULL;
|
||||
int smderlen, r;
|
||||
smderlen = i2d_X509_ALGORS(algs, &smder);
|
||||
if (smderlen <= 0)
|
||||
return 0;
|
||||
r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities,
|
||||
V_ASN1_SEQUENCE, smder, smderlen);
|
||||
OPENSSL_free(smder);
|
||||
return r;
|
||||
}
|
||||
|
||||
int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
|
||||
int algnid, int keysize)
|
||||
{
|
||||
X509_ALGOR *alg;
|
||||
ASN1_INTEGER *key = NULL;
|
||||
if (keysize > 0) {
|
||||
key = ASN1_INTEGER_new();
|
||||
if (!key || !ASN1_INTEGER_set(key, keysize))
|
||||
return 0;
|
||||
}
|
||||
alg = X509_ALGOR_new();
|
||||
if (!alg) {
|
||||
if (key)
|
||||
ASN1_INTEGER_free(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
|
||||
key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key);
|
||||
if (!*algs)
|
||||
*algs = sk_X509_ALGOR_new_null();
|
||||
if (!*algs || !sk_X509_ALGOR_push(*algs, alg)) {
|
||||
X509_ALGOR_free(alg);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check to see if a cipher exists and if so add S/MIME capabilities */
|
||||
|
||||
static int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
|
||||
{
|
||||
if (EVP_get_cipherbynid(nid))
|
||||
return CMS_add_simple_smimecap(sk, nid, arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
|
||||
{
|
||||
if (EVP_get_digestbynid(nid))
|
||||
return CMS_add_simple_smimecap(sk, nid, arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap)
|
||||
{
|
||||
if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
|
||||
|| !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_des_cbc, -1)
|
||||
|| !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
837
cms/lib/cms_smime.c
Normal file
837
cms/lib/cms_smime.c
Normal file
|
@ -0,0 +1,837 @@
|
|||
/* crypto/cms/cms_smime.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
|
||||
{
|
||||
unsigned char buf[4096];
|
||||
int r = 0, i;
|
||||
BIO *tmpout = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
tmpout = BIO_new(BIO_s_null());
|
||||
else if (flags & CMS_TEXT) {
|
||||
tmpout = BIO_new(BIO_s_mem());
|
||||
BIO_set_mem_eof_return(tmpout, 0);
|
||||
} else
|
||||
tmpout = out;
|
||||
|
||||
if (!tmpout) {
|
||||
CMSerr(CMS_F_CMS_COPY_CONTENT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Read all content through chain to process digest, decrypt etc */
|
||||
for (;;) {
|
||||
i = BIO_read(in, buf, sizeof(buf));
|
||||
if (i <= 0) {
|
||||
if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
|
||||
if (!BIO_get_cipher_status(in))
|
||||
goto err;
|
||||
}
|
||||
if (i < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmpout && (BIO_write(tmpout, buf, i) != i))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (flags & CMS_TEXT) {
|
||||
if (!SMIME_text(tmpout, out)) {
|
||||
CMSerr(CMS_F_CMS_COPY_CONTENT, CMS_R_SMIME_TEXT_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
if (tmpout && (tmpout != out))
|
||||
BIO_free(tmpout);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static int check_content(CMS_ContentInfo *cms)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
||||
if (!pos || !*pos) {
|
||||
CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void do_free_upto(BIO *f, BIO *upto)
|
||||
{
|
||||
if (upto) {
|
||||
BIO *tbio;
|
||||
do {
|
||||
tbio = BIO_pop(f);
|
||||
BIO_free(f);
|
||||
f = tbio;
|
||||
}
|
||||
while (f && f != upto);
|
||||
} else
|
||||
BIO_free_all(f);
|
||||
}
|
||||
|
||||
int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
|
||||
{
|
||||
BIO *cont;
|
||||
int r;
|
||||
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
|
||||
CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
|
||||
return 0;
|
||||
}
|
||||
cont = CMS_dataInit(cms, NULL);
|
||||
if (!cont)
|
||||
return 0;
|
||||
r = cms_copy_content(out, cont, flags);
|
||||
BIO_free_all(cont);
|
||||
return r;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
cms = cms_Data_create();
|
||||
if (!cms)
|
||||
return NULL;
|
||||
|
||||
if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
|
||||
return cms;
|
||||
|
||||
CMS_ContentInfo_free(cms);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
||||
unsigned int flags)
|
||||
{
|
||||
BIO *cont;
|
||||
int r;
|
||||
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
|
||||
CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dcont && !check_content(cms))
|
||||
return 0;
|
||||
|
||||
cont = CMS_dataInit(cms, dcont);
|
||||
if (!cont)
|
||||
return 0;
|
||||
r = cms_copy_content(out, cont, flags);
|
||||
if (r)
|
||||
r = cms_DigestedData_do_final(cms, cont, 1);
|
||||
do_free_upto(cont, dcont);
|
||||
return r;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
|
||||
unsigned int flags)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
if (!md)
|
||||
md = EVP_sha1();
|
||||
cms = cms_DigestedData_create(md);
|
||||
if (!cms)
|
||||
return NULL;
|
||||
|
||||
if (!(flags & CMS_DETACHED))
|
||||
CMS_set_detached(cms, 0);
|
||||
|
||||
if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
|
||||
return cms;
|
||||
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
|
||||
const unsigned char *key, size_t keylen,
|
||||
BIO *dcont, BIO *out, unsigned int flags)
|
||||
{
|
||||
BIO *cont;
|
||||
int r;
|
||||
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
|
||||
CMS_R_TYPE_NOT_ENCRYPTED_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dcont && !check_content(cms))
|
||||
return 0;
|
||||
|
||||
if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
|
||||
return 0;
|
||||
cont = CMS_dataInit(cms, dcont);
|
||||
if (!cont)
|
||||
return 0;
|
||||
r = cms_copy_content(out, cont, flags);
|
||||
do_free_upto(cont, dcont);
|
||||
return r;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
|
||||
const unsigned char *key,
|
||||
size_t keylen, unsigned int flags)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
if (!cipher) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
|
||||
return NULL;
|
||||
}
|
||||
cms = CMS_ContentInfo_new();
|
||||
if (!cms)
|
||||
return NULL;
|
||||
if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
|
||||
return NULL;
|
||||
|
||||
if (!(flags & CMS_DETACHED))
|
||||
CMS_set_detached(cms, 0);
|
||||
|
||||
if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
||||
|| CMS_final(cms, in, NULL, flags))
|
||||
return cms;
|
||||
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
|
||||
X509_STORE *store,
|
||||
STACK_OF(X509) *certs,
|
||||
STACK_OF(X509_CRL) *crls,
|
||||
unsigned int flags)
|
||||
{
|
||||
X509_STORE_CTX ctx;
|
||||
X509 *signer;
|
||||
int i, j, r = 0;
|
||||
CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
|
||||
if (!X509_STORE_CTX_init(&ctx, store, signer, certs)) {
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, CMS_R_STORE_INIT_ERROR);
|
||||
goto err;
|
||||
}
|
||||
X509_STORE_CTX_set_default(&ctx, "smime_sign");
|
||||
if (crls)
|
||||
X509_STORE_CTX_set0_crls(&ctx, crls);
|
||||
|
||||
i = X509_verify_cert(&ctx);
|
||||
if (i <= 0) {
|
||||
j = X509_STORE_CTX_get_error(&ctx);
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
|
||||
CMS_R_CERTIFICATE_VERIFY_ERROR);
|
||||
ERR_add_error_data(2, "Verify error:",
|
||||
X509_verify_cert_error_string(j));
|
||||
goto err;
|
||||
}
|
||||
r = 1;
|
||||
err:
|
||||
X509_STORE_CTX_cleanup(&ctx);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
||||
X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
|
||||
{
|
||||
CMS_SignerInfo *si;
|
||||
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||
STACK_OF(X509) *cms_certs = NULL;
|
||||
STACK_OF(X509_CRL) *crls = NULL;
|
||||
X509 *signer;
|
||||
int i, scount = 0, ret = 0;
|
||||
BIO *cmsbio = NULL, *tmpin = NULL;
|
||||
|
||||
if (!dcont && !check_content(cms))
|
||||
return 0;
|
||||
|
||||
/* Attempt to find all signer certificates */
|
||||
|
||||
sinfos = CMS_get0_SignerInfos(cms);
|
||||
|
||||
if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
|
||||
CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
|
||||
if (signer)
|
||||
scount++;
|
||||
}
|
||||
|
||||
if (scount != sk_CMS_SignerInfo_num(sinfos))
|
||||
scount += CMS_set1_signers_certs(cms, certs, flags);
|
||||
|
||||
if (scount != sk_CMS_SignerInfo_num(sinfos)) {
|
||||
CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Attempt to verify all signers certs */
|
||||
|
||||
if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
|
||||
cms_certs = CMS_get1_certs(cms);
|
||||
if (!(flags & CMS_NOCRL))
|
||||
crls = CMS_get1_crls(cms);
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (!cms_signerinfo_verify_cert(si, store,
|
||||
cms_certs, crls, flags))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to verify all SignerInfo signed attribute signatures */
|
||||
|
||||
if (!(flags & CMS_NO_ATTR_VERIFY)) {
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (CMS_signed_get_attr_count(si) < 0)
|
||||
continue;
|
||||
if (CMS_SignerInfo_verify(si) <= 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Performance optimization: if the content is a memory BIO then store
|
||||
* its contents in a temporary read only memory BIO. This avoids
|
||||
* potentially large numbers of slow copies of data which will occur when
|
||||
* reading from a read write memory BIO when signatures are calculated.
|
||||
*/
|
||||
|
||||
if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
|
||||
char *ptr;
|
||||
long len;
|
||||
len = BIO_get_mem_data(dcont, &ptr);
|
||||
tmpin = BIO_new_mem_buf(ptr, len);
|
||||
if (tmpin == NULL) {
|
||||
CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err2;
|
||||
}
|
||||
} else
|
||||
tmpin = dcont;
|
||||
|
||||
cmsbio = CMS_dataInit(cms, tmpin);
|
||||
if (!cmsbio)
|
||||
goto err;
|
||||
|
||||
if (!cms_copy_content(out, cmsbio, flags))
|
||||
goto err;
|
||||
|
||||
if (!(flags & CMS_NO_CONTENT_VERIFY)) {
|
||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||
si = sk_CMS_SignerInfo_value(sinfos, i);
|
||||
if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
|
||||
CMSerr(CMS_F_CMS_VERIFY, CMS_R_CONTENT_VERIFY_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (dcont && (tmpin == dcont))
|
||||
do_free_upto(cmsbio, dcont);
|
||||
else
|
||||
BIO_free_all(cmsbio);
|
||||
|
||||
err2:
|
||||
if (cms_certs)
|
||||
sk_X509_pop_free(cms_certs, X509_free);
|
||||
if (crls)
|
||||
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
|
||||
STACK_OF(X509) *certs,
|
||||
X509_STORE *store, unsigned int flags)
|
||||
{
|
||||
int r;
|
||||
flags &= ~(CMS_DETACHED | CMS_TEXT);
|
||||
r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
return cms_Receipt_verify(rcms, ocms);
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
|
||||
STACK_OF(X509) *certs, BIO *data,
|
||||
unsigned int flags)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
int i;
|
||||
|
||||
cms = CMS_ContentInfo_new();
|
||||
if (!cms || !CMS_SignedData_init(cms))
|
||||
goto merr;
|
||||
|
||||
if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
|
||||
CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < sk_X509_num(certs); i++) {
|
||||
X509 *x = sk_X509_value(certs, i);
|
||||
if (!CMS_add1_cert(cms, x))
|
||||
goto merr;
|
||||
}
|
||||
|
||||
if (!(flags & CMS_DETACHED))
|
||||
CMS_set_detached(cms, 0);
|
||||
|
||||
if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
||||
|| CMS_final(cms, data, NULL, flags))
|
||||
return cms;
|
||||
else
|
||||
goto err;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
err:
|
||||
if (cms)
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
|
||||
X509 *signcert, EVP_PKEY *pkey,
|
||||
STACK_OF(X509) *certs, unsigned int flags)
|
||||
{
|
||||
CMS_SignerInfo *rct_si;
|
||||
CMS_ContentInfo *cms = NULL;
|
||||
ASN1_OCTET_STRING **pos, *os;
|
||||
BIO *rct_cont = NULL;
|
||||
int r = 0;
|
||||
|
||||
flags &= ~(CMS_STREAM | CMS_TEXT);
|
||||
/* Not really detached but avoids content being allocated */
|
||||
flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
|
||||
if (!pkey || !signcert) {
|
||||
CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize signed data */
|
||||
|
||||
cms = CMS_sign(NULL, NULL, certs, NULL, flags);
|
||||
if (!cms)
|
||||
goto err;
|
||||
|
||||
/* Set inner content type to signed receipt */
|
||||
if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
|
||||
goto err;
|
||||
|
||||
rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
|
||||
if (!rct_si) {
|
||||
CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
os = cms_encode_Receipt(si);
|
||||
|
||||
if (!os)
|
||||
goto err;
|
||||
|
||||
/* Set content to digest */
|
||||
rct_cont = BIO_new_mem_buf(os->data, os->length);
|
||||
if (!rct_cont)
|
||||
goto err;
|
||||
|
||||
/* Add msgSigDigest attribute */
|
||||
|
||||
if (!cms_msgSigDigest_add1(rct_si, si))
|
||||
goto err;
|
||||
|
||||
/* Finalize structure */
|
||||
if (!CMS_final(cms, rct_cont, NULL, flags))
|
||||
goto err;
|
||||
|
||||
/* Set embedded content */
|
||||
pos = CMS_get0_content(cms);
|
||||
*pos = os;
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
if (rct_cont)
|
||||
BIO_free(rct_cont);
|
||||
if (r)
|
||||
return cms;
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
|
||||
const EVP_CIPHER *cipher, unsigned int flags)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
int i;
|
||||
X509 *recip;
|
||||
cms = CMS_EnvelopedData_create(cipher);
|
||||
if (!cms)
|
||||
goto merr;
|
||||
for (i = 0; i < sk_X509_num(certs); i++) {
|
||||
recip = sk_X509_value(certs, i);
|
||||
if (!CMS_add1_recipient_cert(cms, recip, flags)) {
|
||||
CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & CMS_DETACHED))
|
||||
CMS_set_detached(cms, 0);
|
||||
|
||||
if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
||||
|| CMS_final(cms, data, NULL, flags))
|
||||
return cms;
|
||||
else
|
||||
goto err;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
if (cms)
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
|
||||
EVP_PKEY *pk, X509 *cert)
|
||||
{
|
||||
int i;
|
||||
STACK_OF(CMS_RecipientEncryptedKey) *reks;
|
||||
CMS_RecipientEncryptedKey *rek;
|
||||
reks = CMS_RecipientInfo_kari_get0_reks(ri);
|
||||
if (!cert)
|
||||
return 0;
|
||||
for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
|
||||
int rv;
|
||||
rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
|
||||
if (CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
|
||||
continue;
|
||||
CMS_RecipientInfo_kari_set0_pkey(ri, pk);
|
||||
rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
|
||||
CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
|
||||
if (rv > 0)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
|
||||
{
|
||||
STACK_OF(CMS_RecipientInfo) *ris;
|
||||
CMS_RecipientInfo *ri;
|
||||
int i, r, ri_type;
|
||||
int debug = 0, match_ri = 0;
|
||||
|
||||
ris = CMS_get0_RecipientInfos(cms);
|
||||
if (ris)
|
||||
debug = cms->d.envelopedData->encryptedContentInfo->debug;
|
||||
ri_type = cms_pkey_get_ri_type(pk);
|
||||
if (ri_type == CMS_RECIPINFO_NONE) {
|
||||
CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
|
||||
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
||||
ri = sk_CMS_RecipientInfo_value(ris, i);
|
||||
if (CMS_RecipientInfo_type(ri) != ri_type)
|
||||
continue;
|
||||
match_ri = 1;
|
||||
if (ri_type == CMS_RECIPINFO_AGREE) {
|
||||
r = cms_kari_set1_pkey(cms, ri, pk, cert);
|
||||
if (r > 0)
|
||||
return 1;
|
||||
if (r < 0)
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* If we have a cert try matching RecipientInfo otherwise try them
|
||||
* all.
|
||||
*/
|
||||
else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
|
||||
CMS_RecipientInfo_set0_pkey(ri, pk);
|
||||
r = CMS_RecipientInfo_decrypt(cms, ri);
|
||||
CMS_RecipientInfo_set0_pkey(ri, NULL);
|
||||
if (cert) {
|
||||
/*
|
||||
* If not debugging clear any error and return success to
|
||||
* avoid leaking of information useful to MMA
|
||||
*/
|
||||
if (!debug) {
|
||||
ERR_clear_error();
|
||||
return 1;
|
||||
}
|
||||
if (r > 0)
|
||||
return 1;
|
||||
CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* If no cert and not debugging don't leave loop after first
|
||||
* successful decrypt. Always attempt to decrypt all recipients
|
||||
* to avoid leaking timing of a successful decrypt.
|
||||
*/
|
||||
else if (r > 0 && debug)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* If no cert and not debugging always return success */
|
||||
if (match_ri && !cert && !debug) {
|
||||
ERR_clear_error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
|
||||
unsigned char *key, size_t keylen,
|
||||
unsigned char *id, size_t idlen)
|
||||
{
|
||||
STACK_OF(CMS_RecipientInfo) *ris;
|
||||
CMS_RecipientInfo *ri;
|
||||
int i, r;
|
||||
ris = CMS_get0_RecipientInfos(cms);
|
||||
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
||||
ri = sk_CMS_RecipientInfo_value(ris, i);
|
||||
if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we have an id try matching RecipientInfo otherwise try them
|
||||
* all.
|
||||
*/
|
||||
if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
|
||||
CMS_RecipientInfo_set0_key(ri, key, keylen);
|
||||
r = CMS_RecipientInfo_decrypt(cms, ri);
|
||||
CMS_RecipientInfo_set0_key(ri, NULL, 0);
|
||||
if (r > 0)
|
||||
return 1;
|
||||
if (id) {
|
||||
CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_DECRYPT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
ERR_clear_error();
|
||||
}
|
||||
}
|
||||
|
||||
CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
|
||||
unsigned char *pass, ossl_ssize_t passlen)
|
||||
{
|
||||
STACK_OF(CMS_RecipientInfo) *ris;
|
||||
CMS_RecipientInfo *ri;
|
||||
int i, r;
|
||||
ris = CMS_get0_RecipientInfos(cms);
|
||||
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
||||
ri = sk_CMS_RecipientInfo_value(ris, i);
|
||||
if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
|
||||
continue;
|
||||
CMS_RecipientInfo_set0_password(ri, pass, passlen);
|
||||
r = CMS_RecipientInfo_decrypt(cms, ri);
|
||||
CMS_RecipientInfo_set0_password(ri, NULL, 0);
|
||||
if (r > 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
|
||||
BIO *dcont, BIO *out, unsigned int flags)
|
||||
{
|
||||
int r;
|
||||
BIO *cont;
|
||||
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) {
|
||||
CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
|
||||
return 0;
|
||||
}
|
||||
if (!dcont && !check_content(cms))
|
||||
return 0;
|
||||
if (flags & CMS_DEBUG_DECRYPT)
|
||||
cms->d.envelopedData->encryptedContentInfo->debug = 1;
|
||||
else
|
||||
cms->d.envelopedData->encryptedContentInfo->debug = 0;
|
||||
if (!pk && !cert && !dcont && !out)
|
||||
return 1;
|
||||
if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
|
||||
return 0;
|
||||
cont = CMS_dataInit(cms, dcont);
|
||||
if (!cont)
|
||||
return 0;
|
||||
r = cms_copy_content(out, cont, flags);
|
||||
do_free_upto(cont, dcont);
|
||||
return r;
|
||||
}
|
||||
|
||||
int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
|
||||
{
|
||||
BIO *cmsbio;
|
||||
int ret = 0;
|
||||
if (!(cmsbio = CMS_dataInit(cms, dcont))) {
|
||||
CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SMIME_crlf_copy(data, cmsbio, flags);
|
||||
|
||||
(void)BIO_flush(cmsbio);
|
||||
|
||||
if (!CMS_dataFinal(cms, cmsbio)) {
|
||||
CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_DATAFINAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
do_free_upto(cmsbio, dcont);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
#ifdef ZLIB
|
||||
|
||||
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
||||
unsigned int flags)
|
||||
{
|
||||
BIO *cont;
|
||||
int r;
|
||||
if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
|
||||
CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dcont && !check_content(cms))
|
||||
return 0;
|
||||
|
||||
cont = CMS_dataInit(cms, dcont);
|
||||
if (!cont)
|
||||
return 0;
|
||||
r = cms_copy_content(out, cont, flags);
|
||||
do_free_upto(cont, dcont);
|
||||
return r;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
|
||||
{
|
||||
CMS_ContentInfo *cms;
|
||||
if (comp_nid <= 0)
|
||||
comp_nid = NID_zlib_compression;
|
||||
cms = cms_CompressedData_create(comp_nid);
|
||||
if (!cms)
|
||||
return NULL;
|
||||
|
||||
if (!(flags & CMS_DETACHED))
|
||||
CMS_set_detached(cms, 0);
|
||||
|
||||
if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
|
||||
return cms;
|
||||
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
||||
unsigned int flags)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
109
cms/lib/cryptlib.h
Normal file
109
cms/lib/cryptlib.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/* crypto/cryptlib.h */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef HEADER_CRYPTLIB_H
|
||||
# define HEADER_CRYPTLIB_H
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
# ifdef OPENSSL_USE_APPLINK
|
||||
# define BIO_FLAGS_UPLINK 0x8000
|
||||
# include "ms/uplink.h"
|
||||
# endif
|
||||
|
||||
# include <openssl/crypto.h>
|
||||
# include <openssl/buffer.h>
|
||||
# include <openssl/bio.h>
|
||||
# include <openssl/err.h>
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
# ifndef OPENSSL_SYS_VMS
|
||||
# define X509_CERT_AREA OPENSSLDIR
|
||||
# define X509_CERT_DIR OPENSSLDIR "/certs"
|
||||
# define X509_CERT_FILE OPENSSLDIR "/cert.pem"
|
||||
# define X509_PRIVATE_DIR OPENSSLDIR "/private"
|
||||
# else
|
||||
# define X509_CERT_AREA "SSLROOT:[000000]"
|
||||
# define X509_CERT_DIR "SSLCERTS:"
|
||||
# define X509_CERT_FILE "SSLCERTS:cert.pem"
|
||||
# define X509_PRIVATE_DIR "SSLPRIVATE:"
|
||||
# endif
|
||||
|
||||
# define X509_CERT_DIR_EVP "SSL_CERT_DIR"
|
||||
# define X509_CERT_FILE_EVP "SSL_CERT_FILE"
|
||||
|
||||
/* size of string representations */
|
||||
# define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1)
|
||||
# define HEX_SIZE(type) (sizeof(type)*2)
|
||||
|
||||
void OPENSSL_cpuid_setup(void);
|
||||
extern unsigned int OPENSSL_ia32cap_P[];
|
||||
void OPENSSL_showfatal(const char *fmta, ...);
|
||||
void *OPENSSL_stderr(void);
|
||||
extern int OPENSSL_NONPIC_relocated;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
370
cms/lib/evp_locl.h
Normal file
370
cms/lib/evp_locl.h
Normal file
|
@ -0,0 +1,370 @@
|
|||
/* $OpenBSD: evp_locl.h,v 1.14 2016/12/21 15:49:29 jsing Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2000.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
__BEGIN_HIDDEN_DECLS
|
||||
|
||||
/* Macros to code block cipher wrappers */
|
||||
|
||||
/* Wrapper functions for each cipher mode */
|
||||
|
||||
#define BLOCK_CIPHER_ecb_loop() \
|
||||
size_t i, bl; \
|
||||
bl = ctx->cipher->block_size;\
|
||||
if(inl < bl) return 1;\
|
||||
inl -= bl; \
|
||||
for(i=0; i <= inl; i+=bl)
|
||||
|
||||
#define BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \
|
||||
static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
|
||||
{\
|
||||
BLOCK_CIPHER_ecb_loop() \
|
||||
cprefix##_ecb_encrypt(in + i, out + i, &((kstruct *)ctx->cipher_data)->ksched, ctx->encrypt);\
|
||||
return 1;\
|
||||
}
|
||||
|
||||
#define EVP_MAXCHUNK ((size_t)1<<(sizeof(long)*8-2))
|
||||
|
||||
#define BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) \
|
||||
static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
|
||||
{\
|
||||
while(inl>=EVP_MAXCHUNK)\
|
||||
{\
|
||||
cprefix##_ofb##cbits##_encrypt(in, out, (long)EVP_MAXCHUNK, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num);\
|
||||
inl-=EVP_MAXCHUNK;\
|
||||
in +=EVP_MAXCHUNK;\
|
||||
out+=EVP_MAXCHUNK;\
|
||||
}\
|
||||
if (inl)\
|
||||
cprefix##_ofb##cbits##_encrypt(in, out, (long)inl, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num);\
|
||||
return 1;\
|
||||
}
|
||||
|
||||
#define BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \
|
||||
static int cname##_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
|
||||
{\
|
||||
while(inl>=EVP_MAXCHUNK) \
|
||||
{\
|
||||
cprefix##_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, ctx->encrypt);\
|
||||
inl-=EVP_MAXCHUNK;\
|
||||
in +=EVP_MAXCHUNK;\
|
||||
out+=EVP_MAXCHUNK;\
|
||||
}\
|
||||
if (inl)\
|
||||
cprefix##_cbc_encrypt(in, out, (long)inl, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, ctx->encrypt);\
|
||||
return 1;\
|
||||
}
|
||||
|
||||
#define BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \
|
||||
static int cname##_cfb##cbits##_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
|
||||
{\
|
||||
size_t chunk=EVP_MAXCHUNK;\
|
||||
if (cbits==1) chunk>>=3;\
|
||||
if (inl<chunk) chunk=inl;\
|
||||
while(inl && inl>=chunk)\
|
||||
{\
|
||||
cprefix##_cfb##cbits##_encrypt(in, out, (long)((cbits==1) && !(ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) ?inl*8:inl), &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num, ctx->encrypt);\
|
||||
inl-=chunk;\
|
||||
in +=chunk;\
|
||||
out+=chunk;\
|
||||
if(inl<chunk) chunk=inl;\
|
||||
}\
|
||||
return 1;\
|
||||
}
|
||||
|
||||
#define BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \
|
||||
BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \
|
||||
BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \
|
||||
BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \
|
||||
BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched)
|
||||
|
||||
#define BLOCK_CIPHER_def1(cname, nmode, mode, MODE, kstruct, nid, block_size, \
|
||||
key_len, iv_len, flags, init_key, cleanup, \
|
||||
set_asn1, get_asn1, ctrl) \
|
||||
static const EVP_CIPHER cname##_##mode = { \
|
||||
nid##_##nmode, block_size, key_len, iv_len, \
|
||||
flags | EVP_CIPH_##MODE##_MODE, \
|
||||
init_key, \
|
||||
cname##_##mode##_cipher, \
|
||||
cleanup, \
|
||||
sizeof(kstruct), \
|
||||
set_asn1, get_asn1,\
|
||||
ctrl, \
|
||||
NULL \
|
||||
}; \
|
||||
const EVP_CIPHER *EVP_##cname##_##mode(void) { return &cname##_##mode; }
|
||||
|
||||
#define BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, \
|
||||
iv_len, flags, init_key, cleanup, set_asn1, \
|
||||
get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def1(cname, cbc, cbc, CBC, kstruct, nid, block_size, key_len, \
|
||||
iv_len, flags, init_key, cleanup, set_asn1, get_asn1, ctrl)
|
||||
|
||||
#define BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, \
|
||||
iv_len, cbits, flags, init_key, cleanup, \
|
||||
set_asn1, get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def1(cname, cfb##cbits, cfb##cbits, CFB, kstruct, nid, 1, \
|
||||
key_len, iv_len, flags, init_key, cleanup, set_asn1, \
|
||||
get_asn1, ctrl)
|
||||
|
||||
#define BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, \
|
||||
iv_len, cbits, flags, init_key, cleanup, \
|
||||
set_asn1, get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def1(cname, ofb##cbits, ofb, OFB, kstruct, nid, 1, \
|
||||
key_len, iv_len, flags, init_key, cleanup, set_asn1, \
|
||||
get_asn1, ctrl)
|
||||
|
||||
#define BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, \
|
||||
flags, init_key, cleanup, set_asn1, \
|
||||
get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def1(cname, ecb, ecb, ECB, kstruct, nid, block_size, key_len, \
|
||||
0, flags, init_key, cleanup, set_asn1, get_asn1, ctrl)
|
||||
|
||||
#define BLOCK_CIPHER_defs(cname, kstruct, \
|
||||
nid, block_size, key_len, iv_len, cbits, flags, \
|
||||
init_key, cleanup, set_asn1, get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, iv_len, flags, \
|
||||
init_key, cleanup, set_asn1, get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, iv_len, cbits, \
|
||||
flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, iv_len, cbits, \
|
||||
flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, flags, \
|
||||
init_key, cleanup, set_asn1, get_asn1, ctrl)
|
||||
|
||||
|
||||
/*
|
||||
#define BLOCK_CIPHER_defs(cname, kstruct, \
|
||||
nid, block_size, key_len, iv_len, flags,\
|
||||
init_key, cleanup, set_asn1, get_asn1, ctrl)\
|
||||
static const EVP_CIPHER cname##_cbc = {\
|
||||
nid##_cbc, block_size, key_len, iv_len, \
|
||||
flags | EVP_CIPH_CBC_MODE,\
|
||||
init_key,\
|
||||
cname##_cbc_cipher,\
|
||||
cleanup,\
|
||||
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
|
||||
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
|
||||
set_asn1, get_asn1,\
|
||||
ctrl, \
|
||||
NULL \
|
||||
};\
|
||||
const EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\
|
||||
static const EVP_CIPHER cname##_cfb = {\
|
||||
nid##_cfb64, 1, key_len, iv_len, \
|
||||
flags | EVP_CIPH_CFB_MODE,\
|
||||
init_key,\
|
||||
cname##_cfb_cipher,\
|
||||
cleanup,\
|
||||
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
|
||||
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
|
||||
set_asn1, get_asn1,\
|
||||
ctrl,\
|
||||
NULL \
|
||||
};\
|
||||
const EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\
|
||||
static const EVP_CIPHER cname##_ofb = {\
|
||||
nid##_ofb64, 1, key_len, iv_len, \
|
||||
flags | EVP_CIPH_OFB_MODE,\
|
||||
init_key,\
|
||||
cname##_ofb_cipher,\
|
||||
cleanup,\
|
||||
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
|
||||
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
|
||||
set_asn1, get_asn1,\
|
||||
ctrl,\
|
||||
NULL \
|
||||
};\
|
||||
const EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\
|
||||
static const EVP_CIPHER cname##_ecb = {\
|
||||
nid##_ecb, block_size, key_len, iv_len, \
|
||||
flags | EVP_CIPH_ECB_MODE,\
|
||||
init_key,\
|
||||
cname##_ecb_cipher,\
|
||||
cleanup,\
|
||||
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
|
||||
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
|
||||
set_asn1, get_asn1,\
|
||||
ctrl,\
|
||||
NULL \
|
||||
};\
|
||||
const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }
|
||||
*/
|
||||
|
||||
#define IMPLEMENT_BLOCK_CIPHER(cname, ksched, cprefix, kstruct, nid, \
|
||||
block_size, key_len, iv_len, cbits, \
|
||||
flags, init_key, \
|
||||
cleanup, set_asn1, get_asn1, ctrl) \
|
||||
BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \
|
||||
BLOCK_CIPHER_defs(cname, kstruct, nid, block_size, key_len, iv_len, \
|
||||
cbits, flags, init_key, cleanup, set_asn1, \
|
||||
get_asn1, ctrl)
|
||||
|
||||
#define EVP_C_DATA(kstruct, ctx) ((kstruct *)(ctx)->cipher_data)
|
||||
|
||||
#define IMPLEMENT_CFBR(cipher,cprefix,kstruct,ksched,keysize,cbits,iv_len) \
|
||||
BLOCK_CIPHER_func_cfb(cipher##_##keysize,cprefix,cbits,kstruct,ksched) \
|
||||
BLOCK_CIPHER_def_cfb(cipher##_##keysize,kstruct, \
|
||||
NID_##cipher##_##keysize, keysize/8, iv_len, cbits, \
|
||||
0, cipher##_init_key, NULL, \
|
||||
EVP_CIPHER_set_asn1_iv, \
|
||||
EVP_CIPHER_get_asn1_iv, \
|
||||
NULL)
|
||||
|
||||
struct evp_pkey_ctx_st {
|
||||
/* Method associated with this operation */
|
||||
const EVP_PKEY_METHOD *pmeth;
|
||||
/* Engine that implements this method or NULL if builtin */
|
||||
ENGINE *engine;
|
||||
/* Key: may be NULL */
|
||||
EVP_PKEY *pkey;
|
||||
/* Peer key for key agreement, may be NULL */
|
||||
EVP_PKEY *peerkey;
|
||||
/* Actual operation */
|
||||
int operation;
|
||||
/* Algorithm specific data */
|
||||
void *data;
|
||||
/* Application specific data */
|
||||
void *app_data;
|
||||
/* Keygen callback */
|
||||
EVP_PKEY_gen_cb *pkey_gencb;
|
||||
/* implementation specific keygen data */
|
||||
int *keygen_info;
|
||||
int keygen_info_count;
|
||||
} /* EVP_PKEY_CTX */;
|
||||
|
||||
#define EVP_PKEY_FLAG_DYNAMIC 1
|
||||
|
||||
struct evp_pkey_method_st {
|
||||
int pkey_id;
|
||||
int flags;
|
||||
|
||||
int (*init)(EVP_PKEY_CTX *ctx);
|
||||
int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
|
||||
void (*cleanup)(EVP_PKEY_CTX *ctx);
|
||||
|
||||
int (*paramgen_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
|
||||
|
||||
int (*keygen_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
|
||||
|
||||
int (*sign_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
const unsigned char *tbs, size_t tbslen);
|
||||
|
||||
int (*verify_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*verify)(EVP_PKEY_CTX *ctx,
|
||||
const unsigned char *sig, size_t siglen,
|
||||
const unsigned char *tbs, size_t tbslen);
|
||||
|
||||
int (*verify_recover_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*verify_recover)(EVP_PKEY_CTX *ctx,
|
||||
unsigned char *rout, size_t *routlen,
|
||||
const unsigned char *sig, size_t siglen);
|
||||
|
||||
int (*signctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
|
||||
int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
EVP_MD_CTX *mctx);
|
||||
|
||||
int (*verifyctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
|
||||
int (*verifyctx)(EVP_PKEY_CTX *ctx, const unsigned char *sig,
|
||||
int siglen, EVP_MD_CTX *mctx);
|
||||
|
||||
int (*encrypt_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*encrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
int (*decrypt_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
int (*derive_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
|
||||
|
||||
int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
|
||||
int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value);
|
||||
} /* EVP_PKEY_METHOD */;
|
||||
|
||||
void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx);
|
||||
|
||||
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
|
||||
ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de);
|
||||
|
||||
/* EVP_AEAD represents a specific AEAD algorithm. */
|
||||
struct evp_aead_st {
|
||||
unsigned char key_len;
|
||||
unsigned char nonce_len;
|
||||
unsigned char overhead;
|
||||
unsigned char max_tag_len;
|
||||
|
||||
int (*init)(struct evp_aead_ctx_st*, const unsigned char *key,
|
||||
size_t key_len, size_t tag_len);
|
||||
void (*cleanup)(struct evp_aead_ctx_st*);
|
||||
|
||||
int (*seal)(const struct evp_aead_ctx_st *ctx, unsigned char *out,
|
||||
size_t *out_len, size_t max_out_len, const unsigned char *nonce,
|
||||
size_t nonce_len, const unsigned char *in, size_t in_len,
|
||||
const unsigned char *ad, size_t ad_len);
|
||||
|
||||
int (*open)(const struct evp_aead_ctx_st *ctx, unsigned char *out,
|
||||
size_t *out_len, size_t max_out_len, const unsigned char *nonce,
|
||||
size_t nonce_len, const unsigned char *in, size_t in_len,
|
||||
const unsigned char *ad, size_t ad_len);
|
||||
};
|
||||
|
||||
__END_HIDDEN_DECLS
|
169
cms/lib/libressl_cms.h
Normal file
169
cms/lib/libressl_cms.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* ====================================================================
|
||||
* Copyright (c) 2008 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
/* this is defined too late here but work */
|
||||
#undef OPENSSL_NO_CMS
|
||||
|
||||
/* ... */
|
||||
typedef ssize_t ossl_ssize_t;
|
||||
typedef size_t ossl_size_t;
|
||||
|
||||
/* safestack.h */
|
||||
#define sk_CMS_CertificateChoices_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_CertificateChoices, (st), (copy_func), (free_func))
|
||||
#define sk_CMS_CertificateChoices_delete(st, i) SKM_sk_delete(CMS_CertificateChoices, (st), (i))
|
||||
#define sk_CMS_CertificateChoices_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_CertificateChoices, (st), (ptr))
|
||||
#define sk_CMS_CertificateChoices_dup(st) SKM_sk_dup(CMS_CertificateChoices, st)
|
||||
#define sk_CMS_CertificateChoices_find(st, val) SKM_sk_find(CMS_CertificateChoices, (st), (val))
|
||||
#define sk_CMS_CertificateChoices_find_ex(st, val) SKM_sk_find_ex(CMS_CertificateChoices, (st), (val))
|
||||
#define sk_CMS_CertificateChoices_free(st) SKM_sk_free(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_insert(st, val, i) SKM_sk_insert(CMS_CertificateChoices, (st), (val), (i))
|
||||
#define sk_CMS_CertificateChoices_is_sorted(st) SKM_sk_is_sorted(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_new(cmp) SKM_sk_new(CMS_CertificateChoices, (cmp))
|
||||
#define sk_CMS_CertificateChoices_new_null() SKM_sk_new_null(CMS_CertificateChoices)
|
||||
#define sk_CMS_CertificateChoices_num(st) SKM_sk_num(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_pop(st) SKM_sk_pop(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_pop_free(st, free_func) SKM_sk_pop_free(CMS_CertificateChoices, (st), (free_func))
|
||||
#define sk_CMS_CertificateChoices_push(st, val) SKM_sk_push(CMS_CertificateChoices, (st), (val))
|
||||
#define sk_CMS_CertificateChoices_set(st, i, val) SKM_sk_set(CMS_CertificateChoices, (st), (i), (val))
|
||||
#define sk_CMS_CertificateChoices_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_CertificateChoices, (st), (cmp))
|
||||
#define sk_CMS_CertificateChoices_shift(st) SKM_sk_shift(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_sort(st) SKM_sk_sort(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_unshift(st, val) SKM_sk_unshift(CMS_CertificateChoices, (st), (val))
|
||||
#define sk_CMS_CertificateChoices_value(st, i) SKM_sk_value(CMS_CertificateChoices, (st), (i))
|
||||
#define sk_CMS_CertificateChoices_zero(st) SKM_sk_zero(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_RecipientEncryptedKey_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_RecipientEncryptedKey, (st), (copy_func), (free_func))
|
||||
#define sk_CMS_RecipientEncryptedKey_delete(st, i) SKM_sk_delete(CMS_RecipientEncryptedKey, (st), (i))
|
||||
#define sk_CMS_RecipientEncryptedKey_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientEncryptedKey, (st), (ptr))
|
||||
#define sk_CMS_RecipientEncryptedKey_dup(st) SKM_sk_dup(CMS_RecipientEncryptedKey, st)
|
||||
#define sk_CMS_RecipientEncryptedKey_find(st, val) SKM_sk_find(CMS_RecipientEncryptedKey, (st), (val))
|
||||
#define sk_CMS_RecipientEncryptedKey_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientEncryptedKey, (st), (val))
|
||||
#define sk_CMS_RecipientEncryptedKey_free(st) SKM_sk_free(CMS_RecipientEncryptedKey, (st))
|
||||
#define sk_CMS_RecipientEncryptedKey_insert(st, val, i) SKM_sk_insert(CMS_RecipientEncryptedKey, (st), (val), (i))
|
||||
#define sk_CMS_RecipientEncryptedKey_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientEncryptedKey, (st))
|
||||
#define sk_CMS_RecipientEncryptedKey_new(cmp) SKM_sk_new(CMS_RecipientEncryptedKey, (cmp))
|
||||
#define sk_CMS_RecipientEncryptedKey_new_null() SKM_sk_new_null(CMS_RecipientEncryptedKey)
|
||||
#define sk_CMS_RecipientEncryptedKey_num(st) SKM_sk_num(CMS_RecipientEncryptedKey, (st))
|
||||
#define sk_CMS_RecipientEncryptedKey_pop(st) SKM_sk_pop(CMS_RecipientEncryptedKey, (st))
|
||||
#define sk_CMS_RecipientEncryptedKey_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientEncryptedKey, (st), (free_func))
|
||||
#define sk_CMS_RecipientEncryptedKey_push(st, val) SKM_sk_push(CMS_RecipientEncryptedKey, (st), (val))
|
||||
#define sk_CMS_RecipientEncryptedKey_set(st, i, val) SKM_sk_set(CMS_RecipientEncryptedKey, (st), (i), (val))
|
||||
#define sk_CMS_RecipientEncryptedKey_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientEncryptedKey, (st), (cmp))
|
||||
#define sk_CMS_RecipientEncryptedKey_shift(st) SKM_sk_shift(CMS_RecipientEncryptedKey, (st))
|
||||
#define sk_CMS_RecipientEncryptedKey_sort(st) SKM_sk_sort(CMS_RecipientEncryptedKey, (st))
|
||||
#define sk_CMS_RecipientEncryptedKey_unshift(st, val) SKM_sk_unshift(CMS_RecipientEncryptedKey, (st), (val))
|
||||
#define sk_CMS_RecipientEncryptedKey_value(st, i) SKM_sk_value(CMS_RecipientEncryptedKey, (st), (i))
|
||||
#define sk_CMS_RecipientEncryptedKey_zero(st) SKM_sk_zero(CMS_RecipientEncryptedKey, (st))
|
||||
#define sk_CMS_RecipientInfo_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_RecipientInfo, (st), (copy_func), (free_func))
|
||||
#define sk_CMS_RecipientInfo_delete(st, i) SKM_sk_delete(CMS_RecipientInfo, (st), (i))
|
||||
#define sk_CMS_RecipientInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientInfo, (st), (ptr))
|
||||
#define sk_CMS_RecipientInfo_dup(st) SKM_sk_dup(CMS_RecipientInfo, st)
|
||||
#define sk_CMS_RecipientInfo_find(st, val) SKM_sk_find(CMS_RecipientInfo, (st), (val))
|
||||
#define sk_CMS_RecipientInfo_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientInfo, (st), (val))
|
||||
#define sk_CMS_RecipientInfo_free(st) SKM_sk_free(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_insert(st, val, i) SKM_sk_insert(CMS_RecipientInfo, (st), (val), (i))
|
||||
#define sk_CMS_RecipientInfo_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_new(cmp) SKM_sk_new(CMS_RecipientInfo, (cmp))
|
||||
#define sk_CMS_RecipientInfo_new_null() SKM_sk_new_null(CMS_RecipientInfo)
|
||||
#define sk_CMS_RecipientInfo_num(st) SKM_sk_num(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_pop(st) SKM_sk_pop(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientInfo, (st), (free_func))
|
||||
#define sk_CMS_RecipientInfo_push(st, val) SKM_sk_push(CMS_RecipientInfo, (st), (val))
|
||||
#define sk_CMS_RecipientInfo_set(st, i, val) SKM_sk_set(CMS_RecipientInfo, (st), (i), (val))
|
||||
#define sk_CMS_RecipientInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientInfo, (st), (cmp))
|
||||
#define sk_CMS_RecipientInfo_shift(st) SKM_sk_shift(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_sort(st) SKM_sk_sort(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_unshift(st, val) SKM_sk_unshift(CMS_RecipientInfo, (st), (val))
|
||||
#define sk_CMS_RecipientInfo_value(st, i) SKM_sk_value(CMS_RecipientInfo, (st), (i))
|
||||
#define sk_CMS_RecipientInfo_zero(st) SKM_sk_zero(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_RevocationInfoChoice, (st), (copy_func), (free_func))
|
||||
#define sk_CMS_RevocationInfoChoice_delete(st, i) SKM_sk_delete(CMS_RevocationInfoChoice, (st), (i))
|
||||
#define sk_CMS_RevocationInfoChoice_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RevocationInfoChoice, (st), (ptr))
|
||||
#define sk_CMS_RevocationInfoChoice_dup(st) SKM_sk_dup(CMS_RevocationInfoChoice, st)
|
||||
#define sk_CMS_RevocationInfoChoice_find(st, val) SKM_sk_find(CMS_RevocationInfoChoice, (st), (val))
|
||||
#define sk_CMS_RevocationInfoChoice_find_ex(st, val) SKM_sk_find_ex(CMS_RevocationInfoChoice, (st), (val))
|
||||
#define sk_CMS_RevocationInfoChoice_free(st) SKM_sk_free(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_insert(st, val, i) SKM_sk_insert(CMS_RevocationInfoChoice, (st), (val), (i))
|
||||
#define sk_CMS_RevocationInfoChoice_is_sorted(st) SKM_sk_is_sorted(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_new(cmp) SKM_sk_new(CMS_RevocationInfoChoice, (cmp))
|
||||
#define sk_CMS_RevocationInfoChoice_new_null() SKM_sk_new_null(CMS_RevocationInfoChoice)
|
||||
#define sk_CMS_RevocationInfoChoice_num(st) SKM_sk_num(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_pop(st) SKM_sk_pop(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_pop_free(st, free_func) SKM_sk_pop_free(CMS_RevocationInfoChoice, (st), (free_func))
|
||||
#define sk_CMS_RevocationInfoChoice_push(st, val) SKM_sk_push(CMS_RevocationInfoChoice, (st), (val))
|
||||
#define sk_CMS_RevocationInfoChoice_set(st, i, val) SKM_sk_set(CMS_RevocationInfoChoice, (st), (i), (val))
|
||||
#define sk_CMS_RevocationInfoChoice_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RevocationInfoChoice, (st), (cmp))
|
||||
#define sk_CMS_RevocationInfoChoice_shift(st) SKM_sk_shift(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_sort(st) SKM_sk_sort(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_unshift(st, val) SKM_sk_unshift(CMS_RevocationInfoChoice, (st), (val))
|
||||
#define sk_CMS_RevocationInfoChoice_value(st, i) SKM_sk_value(CMS_RevocationInfoChoice, (st), (i))
|
||||
#define sk_CMS_RevocationInfoChoice_zero(st) SKM_sk_zero(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_SignerInfo_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_SignerInfo, (st), (copy_func), (free_func))
|
||||
#define sk_CMS_SignerInfo_delete(st, i) SKM_sk_delete(CMS_SignerInfo, (st), (i))
|
||||
#define sk_CMS_SignerInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_SignerInfo, (st), (ptr))
|
||||
#define sk_CMS_SignerInfo_dup(st) SKM_sk_dup(CMS_SignerInfo, st)
|
||||
#define sk_CMS_SignerInfo_find(st, val) SKM_sk_find(CMS_SignerInfo, (st), (val))
|
||||
#define sk_CMS_SignerInfo_find_ex(st, val) SKM_sk_find_ex(CMS_SignerInfo, (st), (val))
|
||||
#define sk_CMS_SignerInfo_free(st) SKM_sk_free(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_insert(st, val, i) SKM_sk_insert(CMS_SignerInfo, (st), (val), (i))
|
||||
#define sk_CMS_SignerInfo_is_sorted(st) SKM_sk_is_sorted(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_new(cmp) SKM_sk_new(CMS_SignerInfo, (cmp))
|
||||
#define sk_CMS_SignerInfo_new_null() SKM_sk_new_null(CMS_SignerInfo)
|
||||
#define sk_CMS_SignerInfo_num(st) SKM_sk_num(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_pop(st) SKM_sk_pop(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_SignerInfo, (st), (free_func))
|
||||
#define sk_CMS_SignerInfo_push(st, val) SKM_sk_push(CMS_SignerInfo, (st), (val))
|
||||
#define sk_CMS_SignerInfo_set(st, i, val) SKM_sk_set(CMS_SignerInfo, (st), (i), (val))
|
||||
#define sk_CMS_SignerInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_SignerInfo, (st), (cmp))
|
||||
#define sk_CMS_SignerInfo_shift(st) SKM_sk_shift(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_sort(st) SKM_sk_sort(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_unshift(st, val) SKM_sk_unshift(CMS_SignerInfo, (st), (val))
|
||||
#define sk_CMS_SignerInfo_value(st, i) SKM_sk_value(CMS_SignerInfo, (st), (i))
|
||||
#define sk_CMS_SignerInfo_zero(st) SKM_sk_zero(CMS_SignerInfo, (st))
|
90
cms/lib/libressl_evp.h
Normal file
90
cms/lib/libressl_evp.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* crypto/evp/evp.h */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
# define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \
|
||||
libressl_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \
|
||||
EVP_PKEY_CTRL_GET_MD, 0, (void *)pmd)
|
||||
|
||||
# define EVP_PKEY_CTRL_GET_MD 13
|
||||
|
||||
#define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8
|
||||
|
||||
/*
|
||||
* WRAP mode stubs
|
||||
*/
|
||||
|
||||
#define EVP_CIPH_WRAP_MODE 0x10002
|
||||
|
||||
/* Cipher context flag to indicate we can handle wrap mode:
|
||||
* if allowed in older applications it could overflow buffers.
|
||||
*/
|
||||
#define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1
|
||||
|
||||
const EVP_CIPHER *EVP_des_ede3_wrap(void);
|
||||
const EVP_CIPHER *EVP_aes_128_wrap(void);
|
||||
const EVP_CIPHER *EVP_aes_192_wrap(void);
|
||||
const EVP_CIPHER *EVP_aes_256_wrap(void);
|
||||
|
||||
const EVP_CIPHER *EVP_des_ede3_wrap(void);
|
||||
const EVP_CIPHER *EVP_aes_128_wrap(void);
|
||||
const EVP_CIPHER *EVP_aes_192_wrap(void);
|
||||
const EVP_CIPHER *EVP_aes_256_wrap(void);
|
698
cms/lib/libressl_pkey.c
Normal file
698
cms/lib/libressl_pkey.c
Normal file
|
@ -0,0 +1,698 @@
|
|||
/* crypto/rsa/rsa_ameth.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include "cms.h"
|
||||
#include "cms_lcl.h"
|
||||
#include "evp_locl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
#include "libressl_evp.h"
|
||||
|
||||
/* RSA pkey context structure */
|
||||
|
||||
typedef struct {
|
||||
/* Key gen parameters */
|
||||
int nbits;
|
||||
BIGNUM *pub_exp;
|
||||
/* Keygen callback info */
|
||||
int gentmp[2];
|
||||
/* RSA padding mode */
|
||||
int pad_mode;
|
||||
/* message digest */
|
||||
const EVP_MD *md;
|
||||
/* message digest for MGF1 */
|
||||
const EVP_MD *mgf1md;
|
||||
/* PSS/OAEP salt length */
|
||||
int saltlen;
|
||||
/* Temp buffer */
|
||||
unsigned char *tbuf;
|
||||
} RSA_PKEY_CTX;
|
||||
|
||||
static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
|
||||
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
|
||||
const char *value);
|
||||
static int rsa_cms_sign(CMS_SignerInfo *si);
|
||||
static int rsa_cms_verify(CMS_SignerInfo *si);
|
||||
static int rsa_cms_decrypt(CMS_RecipientInfo *ri);
|
||||
static int rsa_cms_encrypt(CMS_RecipientInfo *ri);
|
||||
|
||||
int libressl_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
{
|
||||
X509_ALGOR *alg = NULL;
|
||||
|
||||
if (pkey->ameth->pkey_id != EVP_PKEY_RSA)
|
||||
return -2;
|
||||
|
||||
switch (op) {
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_SIGN:
|
||||
if (arg1 == 0)
|
||||
return rsa_cms_sign(arg2);
|
||||
else if (arg1 == 1)
|
||||
return rsa_cms_verify(arg2);
|
||||
break;
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
|
||||
if (arg1 == 0)
|
||||
return rsa_cms_encrypt(arg2);
|
||||
else if (arg1 == 1)
|
||||
return rsa_cms_decrypt(arg2);
|
||||
break;
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_RI_TYPE:
|
||||
*(int *)arg2 = CMS_RECIPINFO_TRANS;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
|
||||
if (alg)
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int libressl_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
|
||||
int cmd, int p1, void *p2)
|
||||
{
|
||||
int ret;
|
||||
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
|
||||
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
return -2;
|
||||
}
|
||||
if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
|
||||
return -1;
|
||||
|
||||
if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
|
||||
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((optype != -1) && !(ctx->operation & optype)) {
|
||||
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->pmeth->pkey_id != EVP_PKEY_RSA)
|
||||
return -1;
|
||||
|
||||
ret = pkey_rsa_ctrl(ctx, cmd, p1, p2);
|
||||
|
||||
if (ret == -2)
|
||||
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int check_padding_md(const EVP_MD *md, int padding)
|
||||
{
|
||||
if (!md)
|
||||
return 1;
|
||||
|
||||
if (padding == RSA_NO_PADDING) {
|
||||
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_PADDING_MODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (padding == RSA_X931_PADDING) {
|
||||
if (RSA_X931_hash_id(EVP_MD_type(md)) == -1) {
|
||||
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_X931_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
switch (type) {
|
||||
case EVP_PKEY_CTRL_RSA_PADDING:
|
||||
if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) {
|
||||
if (!check_padding_md(rctx->md, p1))
|
||||
return 0;
|
||||
if (p1 == RSA_PKCS1_PSS_PADDING) {
|
||||
if (!(ctx->operation &
|
||||
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
|
||||
goto bad_pad;
|
||||
if (!rctx->md)
|
||||
rctx->md = EVP_sha1();
|
||||
} else
|
||||
goto bad_pad;
|
||||
rctx->pad_mode = p1;
|
||||
return 1;
|
||||
}
|
||||
bad_pad:
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL,
|
||||
RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
|
||||
return -2;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_RSA_PADDING:
|
||||
*(int *)p2 = rctx->pad_mode;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
|
||||
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
|
||||
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
|
||||
return -2;
|
||||
}
|
||||
if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN)
|
||||
*(int *)p2 = rctx->saltlen;
|
||||
else {
|
||||
if (p1 < -2)
|
||||
return -2;
|
||||
rctx->saltlen = p1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
|
||||
if (p1 < 256) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS);
|
||||
return -2;
|
||||
}
|
||||
rctx->nbits = p1;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
|
||||
if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_BAD_E_VALUE);
|
||||
return -2;
|
||||
}
|
||||
BN_free(rctx->pub_exp);
|
||||
rctx->pub_exp = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
if (!check_padding_md(p2, rctx->pad_mode))
|
||||
return 0;
|
||||
rctx->md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_MD:
|
||||
*(const EVP_MD **)p2 = rctx->md;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_MGF1_MD:
|
||||
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
|
||||
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
|
||||
return -2;
|
||||
}
|
||||
if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
|
||||
if (rctx->mgf1md)
|
||||
*(const EVP_MD **)p2 = rctx->mgf1md;
|
||||
else
|
||||
*(const EVP_MD **)p2 = rctx->md;
|
||||
} else
|
||||
rctx->mgf1md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_SIGN:
|
||||
return 1;
|
||||
case EVP_PKEY_CTRL_CMS_DECRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_SIGN:
|
||||
return 1;
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL,
|
||||
RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return -2;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int libressl_pkey_ctx_ctrl_str(EVP_PKEY_CTX *ctx, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
|
||||
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
return -2;
|
||||
}
|
||||
if (!strcmp(name, "digest")) {
|
||||
const EVP_MD *md;
|
||||
if (!value || !(md = EVP_get_digestbyname(value))) {
|
||||
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_INVALID_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_signature_md(ctx, md);
|
||||
}
|
||||
return pkey_rsa_ctrl_str(ctx, name, value);
|
||||
}
|
||||
|
||||
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
|
||||
const char *value)
|
||||
{
|
||||
if (!value) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(type, "rsa_padding_mode")) {
|
||||
int pm;
|
||||
if (!strcmp(value, "pkcs1"))
|
||||
pm = RSA_PKCS1_PADDING;
|
||||
else if (!strcmp(value, "sslv23"))
|
||||
pm = RSA_SSLV23_PADDING;
|
||||
else if (!strcmp(value, "none"))
|
||||
pm = RSA_NO_PADDING;
|
||||
else if (!strcmp(value, "x931"))
|
||||
pm = RSA_X931_PADDING;
|
||||
else if (!strcmp(value, "pss"))
|
||||
pm = RSA_PKCS1_PSS_PADDING;
|
||||
else {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
return -2;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
|
||||
}
|
||||
|
||||
if (!strcmp(type, "rsa_pss_saltlen")) {
|
||||
int saltlen;
|
||||
saltlen = atoi(value);
|
||||
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
|
||||
}
|
||||
|
||||
if (!strcmp(type, "rsa_keygen_bits")) {
|
||||
int nbits;
|
||||
nbits = atoi(value);
|
||||
return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
|
||||
}
|
||||
|
||||
if (!strcmp(type, "rsa_keygen_pubexp")) {
|
||||
int ret;
|
||||
BIGNUM *pubexp = NULL;
|
||||
if (!BN_asc2bn(&pubexp, value))
|
||||
return 0;
|
||||
ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
|
||||
if (ret <= 0)
|
||||
BN_free(pubexp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!strcmp(type, "rsa_mgf1_md")) {
|
||||
const EVP_MD *md;
|
||||
if (!(md = EVP_get_digestbyname(value))) {
|
||||
return 0;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
|
||||
static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg)
|
||||
{
|
||||
const unsigned char *p;
|
||||
int plen;
|
||||
if (alg == NULL || alg->parameter == NULL)
|
||||
return NULL;
|
||||
if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
|
||||
return NULL;
|
||||
if (alg->parameter->type != V_ASN1_SEQUENCE)
|
||||
return NULL;
|
||||
|
||||
p = alg->parameter->value.sequence->data;
|
||||
plen = alg->parameter->value.sequence->length;
|
||||
return d2i_X509_ALGOR(NULL, &p, plen);
|
||||
}
|
||||
|
||||
static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
|
||||
X509_ALGOR **pmaskHash)
|
||||
{
|
||||
const unsigned char *p;
|
||||
int plen;
|
||||
RSA_PSS_PARAMS *pss;
|
||||
|
||||
*pmaskHash = NULL;
|
||||
|
||||
if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE)
|
||||
return NULL;
|
||||
p = alg->parameter->value.sequence->data;
|
||||
plen = alg->parameter->value.sequence->length;
|
||||
pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
|
||||
|
||||
if (!pss)
|
||||
return NULL;
|
||||
|
||||
*pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
|
||||
|
||||
return pss;
|
||||
}
|
||||
|
||||
/* allocate and set algorithm ID from EVP_MD, default SHA1 */
|
||||
static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md)
|
||||
{
|
||||
if (EVP_MD_type(md) == NID_sha1)
|
||||
return 1;
|
||||
*palg = X509_ALGOR_new();
|
||||
if (!*palg)
|
||||
return 0;
|
||||
X509_ALGOR_set_md(*palg, md);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allocate and set MGF1 algorithm ID from EVP_MD */
|
||||
static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
|
||||
{
|
||||
X509_ALGOR *algtmp = NULL;
|
||||
ASN1_STRING *stmp = NULL;
|
||||
*palg = NULL;
|
||||
if (EVP_MD_type(mgf1md) == NID_sha1)
|
||||
return 1;
|
||||
/* need to embed algorithm ID inside another */
|
||||
if (!rsa_md_to_algor(&algtmp, mgf1md))
|
||||
goto err;
|
||||
if (!ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp))
|
||||
goto err;
|
||||
*palg = X509_ALGOR_new();
|
||||
if (!*palg)
|
||||
goto err;
|
||||
X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
|
||||
stmp = NULL;
|
||||
err:
|
||||
if (stmp)
|
||||
ASN1_STRING_free(stmp);
|
||||
if (algtmp)
|
||||
X509_ALGOR_free(algtmp);
|
||||
if (*palg)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* convert algorithm ID to EVP_MD, default SHA1 */
|
||||
static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
if (!alg)
|
||||
return EVP_sha1();
|
||||
md = EVP_get_digestbyobj(alg->algorithm);
|
||||
return md;
|
||||
}
|
||||
|
||||
/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
|
||||
static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
if (!alg)
|
||||
return EVP_sha1();
|
||||
/* Check mask and lookup mask hash algorithm */
|
||||
if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
|
||||
return NULL;
|
||||
}
|
||||
if (!maskHash) {
|
||||
return NULL;
|
||||
}
|
||||
md = EVP_get_digestbyobj(maskHash->algorithm);
|
||||
return md;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert EVP_PKEY_CTX is PSS mode into corresponding algorithm parameter,
|
||||
* suitable for setting an AlgorithmIdentifier.
|
||||
*/
|
||||
|
||||
static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
|
||||
{
|
||||
const EVP_MD *sigmd, *mgf1md;
|
||||
RSA_PSS_PARAMS *pss = NULL;
|
||||
ASN1_STRING *os = NULL;
|
||||
EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
|
||||
int saltlen, rv = 0;
|
||||
if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
|
||||
goto err;
|
||||
if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
|
||||
goto err;
|
||||
if (saltlen == -1)
|
||||
saltlen = EVP_MD_size(sigmd);
|
||||
else if (saltlen == -2) {
|
||||
saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
|
||||
if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0)
|
||||
saltlen--;
|
||||
}
|
||||
pss = RSA_PSS_PARAMS_new();
|
||||
if (!pss)
|
||||
goto err;
|
||||
if (saltlen != 20) {
|
||||
pss->saltLength = ASN1_INTEGER_new();
|
||||
if (!pss->saltLength)
|
||||
goto err;
|
||||
if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
|
||||
goto err;
|
||||
}
|
||||
if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
|
||||
goto err;
|
||||
if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
|
||||
goto err;
|
||||
/* Finally create string with pss parameter encoding. */
|
||||
if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os))
|
||||
goto err;
|
||||
rv = 1;
|
||||
err:
|
||||
if (pss)
|
||||
RSA_PSS_PARAMS_free(pss);
|
||||
if (rv)
|
||||
return os;
|
||||
if (os)
|
||||
ASN1_STRING_free(os);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* From PSS AlgorithmIdentifier set public key parameters. If pkey isn't NULL
|
||||
* then the EVP_MD_CTX is setup and initalised. If it is NULL parameters are
|
||||
* passed to pkctx instead.
|
||||
*/
|
||||
|
||||
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
|
||||
X509_ALGOR *sigalg, EVP_PKEY *pkey)
|
||||
{
|
||||
int rv = -1;
|
||||
int saltlen;
|
||||
const EVP_MD *mgf1md = NULL, *md = NULL;
|
||||
RSA_PSS_PARAMS *pss;
|
||||
X509_ALGOR *maskHash;
|
||||
/* Sanity check: make sure it is PSS */
|
||||
if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
|
||||
return -1;
|
||||
}
|
||||
/* Decode PSS parameters */
|
||||
pss = rsa_pss_decode(sigalg, &maskHash);
|
||||
|
||||
if (pss == NULL) {
|
||||
goto err;
|
||||
}
|
||||
mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
|
||||
if (!mgf1md)
|
||||
goto err;
|
||||
md = rsa_algor_to_md(pss->hashAlgorithm);
|
||||
if (!md)
|
||||
goto err;
|
||||
|
||||
if (pss->saltLength) {
|
||||
saltlen = ASN1_INTEGER_get(pss->saltLength);
|
||||
|
||||
/*
|
||||
* Could perform more salt length sanity checks but the main RSA
|
||||
* routines will trap other invalid values anyway.
|
||||
*/
|
||||
if (saltlen < 0) {
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
saltlen = 20;
|
||||
|
||||
/*
|
||||
* low-level routines support only trailer field 0xbc (value 1) and
|
||||
* PKCS#1 says we should reject any other value anyway.
|
||||
*/
|
||||
if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We have all parameters now set up context */
|
||||
|
||||
if (pkey) {
|
||||
if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
|
||||
goto err;
|
||||
} else {
|
||||
const EVP_MD *checkmd;
|
||||
if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0)
|
||||
goto err;
|
||||
if (EVP_MD_type(md) != EVP_MD_type(checkmd)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
|
||||
goto err;
|
||||
/* Carry on */
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
RSA_PSS_PARAMS_free(pss);
|
||||
if (maskHash)
|
||||
X509_ALGOR_free(maskHash);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int rsa_cms_verify(CMS_SignerInfo *si)
|
||||
{
|
||||
int nid, nid2;
|
||||
X509_ALGOR *alg;
|
||||
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
|
||||
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
|
||||
nid = OBJ_obj2nid(alg->algorithm);
|
||||
if (nid == NID_rsaEncryption)
|
||||
return 1;
|
||||
if (nid == NID_rsassaPss)
|
||||
return rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
|
||||
/* Workaround for some implementation that use a signature OID */
|
||||
if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
|
||||
if (nid2 == NID_rsaEncryption)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsa_cms_sign(CMS_SignerInfo *si)
|
||||
{
|
||||
int pad_mode = RSA_PKCS1_PADDING;
|
||||
X509_ALGOR *alg;
|
||||
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
|
||||
ASN1_STRING *os = NULL;
|
||||
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
|
||||
if (pkctx) {
|
||||
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (pad_mode == RSA_PKCS1_PADDING) {
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
/* We don't support it */
|
||||
if (pad_mode != RSA_PKCS1_PSS_PADDING)
|
||||
return 0;
|
||||
os = rsa_ctx_to_pss(pkctx);
|
||||
if (!os)
|
||||
return 0;
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
EVP_PKEY_CTX *pkctx;
|
||||
X509_ALGOR *cmsalg;
|
||||
int nid;
|
||||
pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (!pkctx)
|
||||
return 0;
|
||||
if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
|
||||
return -1;
|
||||
nid = OBJ_obj2nid(cmsalg->algorithm);
|
||||
if (nid == NID_rsaEncryption)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
X509_ALGOR *alg;
|
||||
EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
int pad_mode = RSA_PKCS1_PADDING;
|
||||
CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg);
|
||||
if (pkctx) {
|
||||
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (pad_mode == RSA_PKCS1_PADDING) {
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
147
cms/lib/libressl_stubs.c
Normal file
147
cms/lib/libressl_stubs.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
static int
|
||||
do_cipher_not_implemented(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
init_not_implemented(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_CIPHER des3_wrap = {
|
||||
.nid = NID_id_smime_alg_CMS3DESwrap,
|
||||
.block_size = 8,
|
||||
.key_len = 24,
|
||||
.iv_len = 0,
|
||||
.flags = EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT,
|
||||
|
||||
.init = init_not_implemented,
|
||||
.do_cipher = do_cipher_not_implemented,
|
||||
.ctx_size = 0
|
||||
};
|
||||
|
||||
const EVP_CIPHER *
|
||||
EVP_des_ede3_wrap(void)
|
||||
{
|
||||
return &des3_wrap;
|
||||
}
|
||||
|
||||
static const EVP_CIPHER aes_128_wrap = {
|
||||
.nid = NID_id_aes128_wrap,
|
||||
.block_size = 8,
|
||||
.key_len = 16,
|
||||
.iv_len = 8,
|
||||
.flags = EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT,
|
||||
|
||||
.init = init_not_implemented,
|
||||
.do_cipher = do_cipher_not_implemented,
|
||||
.ctx_size = 0
|
||||
};
|
||||
|
||||
const EVP_CIPHER *
|
||||
EVP_aes_128_wrap(void)
|
||||
{
|
||||
return &aes_128_wrap;
|
||||
}
|
||||
|
||||
static const EVP_CIPHER aes_192_wrap = {
|
||||
.nid = NID_id_aes192_wrap,
|
||||
.block_size = 8,
|
||||
.key_len = 24,
|
||||
.iv_len = 8,
|
||||
.flags = EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT,
|
||||
|
||||
.init = init_not_implemented,
|
||||
.do_cipher = do_cipher_not_implemented,
|
||||
.ctx_size = 0
|
||||
};
|
||||
|
||||
const EVP_CIPHER *
|
||||
EVP_aes_192_wrap(void)
|
||||
{
|
||||
return &aes_192_wrap;
|
||||
}
|
||||
|
||||
static const EVP_CIPHER aes_256_wrap = {
|
||||
.nid = NID_id_aes256_wrap,
|
||||
.block_size = 8,
|
||||
.key_len = 32,
|
||||
.iv_len = 8,
|
||||
.flags = EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT,
|
||||
|
||||
.init = init_not_implemented,
|
||||
.do_cipher = do_cipher_not_implemented,
|
||||
.ctx_size = 0
|
||||
};
|
||||
|
||||
const EVP_CIPHER *
|
||||
EVP_aes_256_wrap(void)
|
||||
{
|
||||
return &aes_256_wrap;
|
||||
}
|
BIN
extras/ovf-env.iso
Normal file
BIN
extras/ovf-env.iso
Normal file
Binary file not shown.
43
extras/ovf-env.xml
Normal file
43
extras/ovf-env.xml
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Environment xmlns="http://schemas.dmtf.org/ovf/environment/1" xmlns:oe="http://schemas.dmtf.org/ovf/environment/1" xmlns:wa="http://schemas.microsoft.com/windowsazure" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<wa:ProvisioningSection>
|
||||
<wa:Version>1.0</wa:Version>
|
||||
<LinuxProvisioningConfigurationSet xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
|
||||
<HostName>openbsd-02</HostName>
|
||||
<UserName>azureuser</UserName>
|
||||
<UserPassword>4Wd-kPV-6wR-dGG</UserPassword>
|
||||
<DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication>
|
||||
<SSH>
|
||||
<PublicKeys>
|
||||
<PublicKey>
|
||||
<Fingerprint>EB0C0AB4B2D5FC35F2F0658D19F44C8283E2DD62</Fingerprint>
|
||||
<Path>$HOME/UserName/.ssh/authorized_keys</Path>
|
||||
</PublicKey>
|
||||
<PublicKey>
|
||||
<Fingerprint>EB0C0AB4B2D5FC35F2F0658D19F44C8283E2DD64</Fingerprint>
|
||||
<Path>$HOME/UserName/.ssh/authorized_keys</Path>
|
||||
</PublicKey>
|
||||
</PublicKeys>
|
||||
<KeyPairs>
|
||||
<KeyPair>
|
||||
<Fingerprint>EB0C0AB4B2D5FC35F2F0658D19F44C8283E2DD66</Fingerprint>
|
||||
<Path>$HOME/UserName/.ssh/id_rsa</Path>
|
||||
</KeyPair>
|
||||
</KeyPairs>
|
||||
</SSH>
|
||||
<CustomData>CustomData</CustomData>
|
||||
</LinuxProvisioningConfigurationSet>
|
||||
</wa:ProvisioningSection>
|
||||
<wa:PlatformSettingsSection>
|
||||
<wa:Version>1.0</wa:Version>
|
||||
<PlatformSettings xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<KmsServerHostname>kms.core.windows.net</KmsServerHostname>
|
||||
<ProvisionGuestAgent>true</ProvisionGuestAgent>
|
||||
<GuestAgentPackageName>Win7_Win8_IaaS_rd_art_stable_161027-1341_GuestAgentPackage.zip</GuestAgentPackageName>
|
||||
<UseAVMA>false</UseAVMA>
|
||||
<RetainWindowsPEPassInUnattend>false</RetainWindowsPEPassInUnattend>
|
||||
<RetainOfflineServicingPassInUnattend>false</RetainOfflineServicingPassInUnattend>
|
||||
</PlatformSettings>
|
||||
</wa:PlatformSettingsSection>
|
||||
</Environment>
|
Loading…
Reference in a new issue