And so it begins...
Initial support for CMS. Add zlib compression BIO. Add AES key wrap implementation. Generalize S/MIME MIME code to support CMS and/or PKCS7.
This commit is contained in:
parent
27dc105f51
commit
8931b30d84
12
CHANGES
12
CHANGES
@ -4,6 +4,18 @@
|
||||
|
||||
Changes between 0.9.8g and 0.9.9 [xx XXX xxxx]
|
||||
|
||||
*) Initial support for Cryptographic Message Syntax (aka CMS) based
|
||||
on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility,
|
||||
support for data, signedData, compressedData types currently included,
|
||||
more to come. Scripts to check against RFC4134 examples draft and internal
|
||||
consistency.
|
||||
[Steve Henson]
|
||||
|
||||
*) Zlib compression BIO. This is a filter BIO which compressed and
|
||||
uncompresses any data passed through it. Add options to enc utility
|
||||
to support it.
|
||||
[Steve Henson]
|
||||
|
||||
*) Extend mk1mf to support importing of options and assembly language
|
||||
files from Configure script, currently only included in VC-WIN32.
|
||||
The assembly language rules can now optionally generate the source
|
||||
|
@ -119,7 +119,7 @@ SDIRS= \
|
||||
bn ec rsa dsa ecdsa dh ecdh dso engine \
|
||||
buffer bio stack lhash rand err \
|
||||
evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui krb5 \
|
||||
store pqueue ts
|
||||
store cms pqueue ts
|
||||
# keep in mind that the above list is adjusted by ./Configure
|
||||
# according to no-xxx arguments...
|
||||
|
||||
|
807
apps/Makefile
807
apps/Makefile
File diff suppressed because it is too large
Load Diff
@ -182,7 +182,7 @@ extern BIO *bio_err;
|
||||
do { CONF_modules_unload(1); destroy_ui_method(); \
|
||||
OBJ_cleanup(); EVP_cleanup(); ENGINE_cleanup(); \
|
||||
CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); \
|
||||
ERR_free_strings(); } while(0)
|
||||
ERR_free_strings(); COMP_zlib_cleanup();} while(0)
|
||||
# else
|
||||
# define apps_startup() \
|
||||
do { do_pipe_sig(); CRYPTO_malloc_init(); \
|
||||
|
927
apps/cms.c
Normal file
927
apps/cms.c
Normal file
@ -0,0 +1,927 @@
|
||||
/* apps/cms.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.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/* CMS utility function */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "apps.h"
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/cms.h>
|
||||
|
||||
#undef PROG
|
||||
#define PROG cms_main
|
||||
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
|
||||
static int smime_cb(int ok, X509_STORE_CTX *ctx);
|
||||
|
||||
#define SMIME_OP 0x10
|
||||
#define SMIME_IP 0x20
|
||||
#define SMIME_SIGNERS 0x40
|
||||
#define SMIME_ENCRYPT (1 | SMIME_OP)
|
||||
#define SMIME_DECRYPT (2 | SMIME_IP)
|
||||
#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
|
||||
#define SMIME_VERIFY (4 | SMIME_IP)
|
||||
#define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP)
|
||||
#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
|
||||
#define SMIME_DATAOUT (7 | SMIME_IP)
|
||||
#define SMIME_DATA_CREATE (8 | SMIME_OP)
|
||||
#define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
|
||||
#define SMIME_DIGEST_CREATE (10 | SMIME_OP)
|
||||
#define SMIME_UNCOMPRESS (11 | SMIME_IP)
|
||||
#define SMIME_COMPRESS (12 | SMIME_OP)
|
||||
|
||||
int MAIN(int, char **);
|
||||
|
||||
int MAIN(int argc, char **argv)
|
||||
{
|
||||
ENGINE *e = NULL;
|
||||
int operation = 0;
|
||||
int ret = 0;
|
||||
char **args;
|
||||
const char *inmode = "r", *outmode = "w";
|
||||
char *infile = NULL, *outfile = NULL;
|
||||
char *signerfile = NULL, *recipfile = NULL;
|
||||
STACK *sksigners = NULL, *skkeys = NULL;
|
||||
char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
|
||||
const EVP_CIPHER *cipher = NULL;
|
||||
CMS_ContentInfo *cms = NULL;
|
||||
X509_STORE *store = NULL;
|
||||
X509 *cert = NULL, *recip = NULL, *signer = NULL;
|
||||
EVP_PKEY *key = NULL;
|
||||
STACK_OF(X509) *encerts = NULL, *other = NULL;
|
||||
BIO *in = NULL, *out = NULL, *indata = NULL;
|
||||
int badarg = 0;
|
||||
int flags = CMS_DETACHED;
|
||||
char *to = NULL, *from = NULL, *subject = NULL;
|
||||
char *CAfile = NULL, *CApath = NULL;
|
||||
char *passargin = NULL, *passin = NULL;
|
||||
char *inrand = NULL;
|
||||
int need_rand = 0;
|
||||
int indef = 0;
|
||||
const EVP_MD *sign_md = NULL;
|
||||
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
|
||||
int keyform = FORMAT_PEM;
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
char *engine=NULL;
|
||||
#endif
|
||||
|
||||
X509_VERIFY_PARAM *vpm = NULL;
|
||||
|
||||
args = argv + 1;
|
||||
ret = 1;
|
||||
|
||||
apps_startup();
|
||||
|
||||
if (bio_err == NULL)
|
||||
{
|
||||
if ((bio_err = BIO_new(BIO_s_file())) != NULL)
|
||||
BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
|
||||
}
|
||||
|
||||
if (!load_config(bio_err, NULL))
|
||||
goto end;
|
||||
|
||||
while (!badarg && *args && *args[0] == '-')
|
||||
{
|
||||
if (!strcmp (*args, "-encrypt"))
|
||||
operation = SMIME_ENCRYPT;
|
||||
else if (!strcmp (*args, "-decrypt"))
|
||||
operation = SMIME_DECRYPT;
|
||||
else if (!strcmp (*args, "-sign"))
|
||||
operation = SMIME_SIGN;
|
||||
else if (!strcmp (*args, "-resign"))
|
||||
operation = SMIME_RESIGN;
|
||||
else if (!strcmp (*args, "-verify"))
|
||||
operation = SMIME_VERIFY;
|
||||
else if (!strcmp (*args, "-cmsout"))
|
||||
operation = SMIME_CMSOUT;
|
||||
else if (!strcmp (*args, "-data_out"))
|
||||
operation = SMIME_DATAOUT;
|
||||
else if (!strcmp (*args, "-data_create"))
|
||||
operation = SMIME_DATA_CREATE;
|
||||
else if (!strcmp (*args, "-digest_verify"))
|
||||
operation = SMIME_DIGEST_VERIFY;
|
||||
else if (!strcmp (*args, "-digest_create"))
|
||||
operation = SMIME_DIGEST_CREATE;
|
||||
else if (!strcmp (*args, "-compress"))
|
||||
operation = SMIME_COMPRESS;
|
||||
else if (!strcmp (*args, "-uncompress"))
|
||||
operation = SMIME_UNCOMPRESS;
|
||||
#ifndef OPENSSL_NO_DES
|
||||
else if (!strcmp (*args, "-des3"))
|
||||
cipher = EVP_des_ede3_cbc();
|
||||
else if (!strcmp (*args, "-des"))
|
||||
cipher = EVP_des_cbc();
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SEED
|
||||
else if (!strcmp (*args, "-seed"))
|
||||
cipher = EVP_seed_cbc();
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_RC2
|
||||
else if (!strcmp (*args, "-rc2-40"))
|
||||
cipher = EVP_rc2_40_cbc();
|
||||
else if (!strcmp (*args, "-rc2-128"))
|
||||
cipher = EVP_rc2_cbc();
|
||||
else if (!strcmp (*args, "-rc2-64"))
|
||||
cipher = EVP_rc2_64_cbc();
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_AES
|
||||
else if (!strcmp(*args,"-aes128"))
|
||||
cipher = EVP_aes_128_cbc();
|
||||
else if (!strcmp(*args,"-aes192"))
|
||||
cipher = EVP_aes_192_cbc();
|
||||
else if (!strcmp(*args,"-aes256"))
|
||||
cipher = EVP_aes_256_cbc();
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CAMELLIA
|
||||
else if (!strcmp(*args,"-camellia128"))
|
||||
cipher = EVP_camellia_128_cbc();
|
||||
else if (!strcmp(*args,"-camellia192"))
|
||||
cipher = EVP_camellia_192_cbc();
|
||||
else if (!strcmp(*args,"-camellia256"))
|
||||
cipher = EVP_camellia_256_cbc();
|
||||
#endif
|
||||
else if (!strcmp (*args, "-text"))
|
||||
flags |= CMS_TEXT;
|
||||
else if (!strcmp (*args, "-nointern"))
|
||||
flags |= CMS_NOINTERN;
|
||||
else if (!strcmp (*args, "-noverify")
|
||||
|| !strcmp (*args, "-no_signer_cert_verify"))
|
||||
flags |= CMS_NO_SIGNER_CERT_VERIFY;
|
||||
else if (!strcmp (*args, "-nocerts"))
|
||||
flags |= CMS_NOCERTS;
|
||||
else if (!strcmp (*args, "-noattr"))
|
||||
flags |= CMS_NOATTR;
|
||||
else if (!strcmp (*args, "-nodetach"))
|
||||
flags &= ~CMS_DETACHED;
|
||||
else if (!strcmp (*args, "-nosmimecap"))
|
||||
flags |= CMS_NOSMIMECAP;
|
||||
else if (!strcmp (*args, "-binary"))
|
||||
flags |= CMS_BINARY;
|
||||
else if (!strcmp (*args, "-keyid"))
|
||||
flags |= CMS_USE_KEYID;
|
||||
else if (!strcmp (*args, "-nosigs"))
|
||||
flags |= CMS_NOSIGS;
|
||||
else if (!strcmp (*args, "-no_content_verify"))
|
||||
flags |= CMS_NO_CONTENT_VERIFY;
|
||||
else if (!strcmp (*args, "-no_attr_verify"))
|
||||
flags |= CMS_NO_ATTR_VERIFY;
|
||||
else if (!strcmp (*args, "-stream"))
|
||||
indef = 1;
|
||||
else if (!strcmp (*args, "-indef"))
|
||||
indef = 1;
|
||||
else if (!strcmp (*args, "-noindef"))
|
||||
indef = 0;
|
||||
else if (!strcmp (*args, "-nooldmime"))
|
||||
flags |= CMS_NOOLDMIMETYPE;
|
||||
else if (!strcmp (*args, "-crlfeol"))
|
||||
flags |= CMS_CRLFEOL;
|
||||
else if (!strcmp(*args,"-rand"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
args++;
|
||||
inrand = *args;
|
||||
need_rand = 1;
|
||||
}
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
else if (!strcmp(*args,"-engine"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
engine = *++args;
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(*args,"-passin"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
passargin = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-to"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
to = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-from"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
from = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-subject"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
subject = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-signer"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
/* If previous -signer argument add signer to list */
|
||||
|
||||
if (signerfile)
|
||||
{
|
||||
if (!sksigners)
|
||||
sksigners = sk_new_null();
|
||||
sk_push(sksigners, signerfile);
|
||||
if (!keyfile)
|
||||
keyfile = signerfile;
|
||||
if (!skkeys)
|
||||
skkeys = sk_new_null();
|
||||
sk_push(skkeys, keyfile);
|
||||
keyfile = NULL;
|
||||
}
|
||||
signerfile = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-recip"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
recipfile = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-md"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
sign_md = EVP_get_digestbyname(*++args);
|
||||
if (sign_md == NULL)
|
||||
{
|
||||
BIO_printf(bio_err, "Unknown digest %s\n",
|
||||
*args);
|
||||
goto argerr;
|
||||
}
|
||||
}
|
||||
else if (!strcmp (*args, "-inkey"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
/* If previous -inkey arument add signer to list */
|
||||
if (keyfile)
|
||||
{
|
||||
if (!signerfile)
|
||||
{
|
||||
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
|
||||
goto argerr;
|
||||
}
|
||||
if (!sksigners)
|
||||
sksigners = sk_new_null();
|
||||
sk_push(sksigners, signerfile);
|
||||
signerfile = NULL;
|
||||
if (!skkeys)
|
||||
skkeys = sk_new_null();
|
||||
sk_push(skkeys, keyfile);
|
||||
}
|
||||
keyfile = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-keyform"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
keyform = str2fmt(*++args);
|
||||
}
|
||||
else if (!strcmp (*args, "-certfile"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
certfile = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-CAfile"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
CAfile = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-CApath"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
CApath = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-in"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
infile = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-inform"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
informat = str2fmt(*++args);
|
||||
}
|
||||
else if (!strcmp (*args, "-outform"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
outformat = str2fmt(*++args);
|
||||
}
|
||||
else if (!strcmp (*args, "-out"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
outfile = *++args;
|
||||
}
|
||||
else if (!strcmp (*args, "-content"))
|
||||
{
|
||||
if (!args[1])
|
||||
goto argerr;
|
||||
contfile = *++args;
|
||||
}
|
||||
else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
|
||||
continue;
|
||||
else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
|
||||
badarg = 1;
|
||||
args++;
|
||||
}
|
||||
|
||||
if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners))
|
||||
{
|
||||
BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
|
||||
goto argerr;
|
||||
}
|
||||
|
||||
if (operation & SMIME_SIGNERS)
|
||||
{
|
||||
/* Check to see if any final signer needs to be appended */
|
||||
if (keyfile && !signerfile)
|
||||
{
|
||||
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
|
||||
goto argerr;
|
||||
}
|
||||
if (signerfile)
|
||||
{
|
||||
if (!sksigners)
|
||||
sksigners = sk_new_null();
|
||||
sk_push(sksigners, signerfile);
|
||||
if (!skkeys)
|
||||
skkeys = sk_new_null();
|
||||
if (!keyfile)
|
||||
keyfile = signerfile;
|
||||
sk_push(skkeys, keyfile);
|
||||
}
|
||||
if (!sksigners)
|
||||
{
|
||||
BIO_printf(bio_err, "No signer certificate specified\n");
|
||||
badarg = 1;
|
||||
}
|
||||
signerfile = NULL;
|
||||
keyfile = NULL;
|
||||
need_rand = 1;
|
||||
}
|
||||
else if (operation == SMIME_DECRYPT)
|
||||
{
|
||||
if (!recipfile && !keyfile)
|
||||
{
|
||||
BIO_printf(bio_err, "No recipient certificate or key specified\n");
|
||||
badarg = 1;
|
||||
}
|
||||
}
|
||||
else if (operation == SMIME_ENCRYPT)
|
||||
{
|
||||
if (!*args)
|
||||
{
|
||||
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
|
||||
badarg = 1;
|
||||
}
|
||||
need_rand = 1;
|
||||
}
|
||||
else if (!operation)
|
||||
badarg = 1;
|
||||
|
||||
if (badarg)
|
||||
{
|
||||
argerr:
|
||||
BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n");
|
||||
BIO_printf (bio_err, "where options are\n");
|
||||
BIO_printf (bio_err, "-encrypt encrypt message\n");
|
||||
BIO_printf (bio_err, "-decrypt decrypt encrypted message\n");
|
||||
BIO_printf (bio_err, "-sign sign message\n");
|
||||
BIO_printf (bio_err, "-verify verify signed message\n");
|
||||
BIO_printf (bio_err, "-cmsout output CMS structure\n");
|
||||
#ifndef OPENSSL_NO_DES
|
||||
BIO_printf (bio_err, "-des3 encrypt with triple DES\n");
|
||||
BIO_printf (bio_err, "-des encrypt with DES\n");
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SEED
|
||||
BIO_printf (bio_err, "-seed encrypt with SEED\n");
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_RC2
|
||||
BIO_printf (bio_err, "-rc2-40 encrypt with RC2-40 (default)\n");
|
||||
BIO_printf (bio_err, "-rc2-64 encrypt with RC2-64\n");
|
||||
BIO_printf (bio_err, "-rc2-128 encrypt with RC2-128\n");
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_AES
|
||||
BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
|
||||
BIO_printf (bio_err, " encrypt PEM output with cbc aes\n");
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CAMELLIA
|
||||
BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
|
||||
BIO_printf (bio_err, " encrypt PEM output with cbc camellia\n");
|
||||
#endif
|
||||
BIO_printf (bio_err, "-nointern don't search certificates in message for signer\n");
|
||||
BIO_printf (bio_err, "-nosigs don't verify message signature\n");
|
||||
BIO_printf (bio_err, "-noverify don't verify signers certificate\n");
|
||||
BIO_printf (bio_err, "-nocerts don't include signers certificate when signing\n");
|
||||
BIO_printf (bio_err, "-nodetach use opaque signing\n");
|
||||
BIO_printf (bio_err, "-noattr don't include any signed attributes\n");
|
||||
BIO_printf (bio_err, "-binary don't translate message to text\n");
|
||||
BIO_printf (bio_err, "-certfile file other certificates file\n");
|
||||
BIO_printf (bio_err, "-signer file signer certificate file\n");
|
||||
BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n");
|
||||
BIO_printf (bio_err, "-skeyid use subject key identifier\n");
|
||||
BIO_printf (bio_err, "-in file input file\n");
|
||||
BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n");
|
||||
BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n");
|
||||
BIO_printf (bio_err, "-keyform arg input private key format (PEM or ENGINE)\n");
|
||||
BIO_printf (bio_err, "-out file output file\n");
|
||||
BIO_printf (bio_err, "-outform arg output format SMIME (default), PEM or DER\n");
|
||||
BIO_printf (bio_err, "-content file supply or override content for detached signature\n");
|
||||
BIO_printf (bio_err, "-to addr to address\n");
|
||||
BIO_printf (bio_err, "-from ad from address\n");
|
||||
BIO_printf (bio_err, "-subject s subject\n");
|
||||
BIO_printf (bio_err, "-text include or delete text MIME headers\n");
|
||||
BIO_printf (bio_err, "-CApath dir trusted certificates directory\n");
|
||||
BIO_printf (bio_err, "-CAfile file trusted certificates file\n");
|
||||
BIO_printf (bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n");
|
||||
BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n");
|
||||
#endif
|
||||
BIO_printf (bio_err, "-passin arg input file pass phrase source\n");
|
||||
BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
|
||||
BIO_printf(bio_err, " load the file (or the files in the directory) into\n");
|
||||
BIO_printf(bio_err, " the random number generator\n");
|
||||
BIO_printf (bio_err, "cert.pem recipient certificate(s) for encryption\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
e = setup_engine(bio_err, engine, 0);
|
||||
#endif
|
||||
|
||||
if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
|
||||
{
|
||||
BIO_printf(bio_err, "Error getting password\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (need_rand)
|
||||
{
|
||||
app_RAND_load_file(NULL, bio_err, (inrand != NULL));
|
||||
if (inrand != NULL)
|
||||
BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
|
||||
app_RAND_load_files(inrand));
|
||||
}
|
||||
|
||||
ret = 2;
|
||||
|
||||
if (!(operation & SMIME_SIGNERS))
|
||||
flags &= ~CMS_DETACHED;
|
||||
|
||||
if (operation & SMIME_OP)
|
||||
{
|
||||
if (outformat == FORMAT_ASN1)
|
||||
outmode = "wb";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & CMS_BINARY)
|
||||
outmode = "wb";
|
||||
}
|
||||
|
||||
if (operation & SMIME_IP)
|
||||
{
|
||||
if (informat == FORMAT_ASN1)
|
||||
inmode = "rb";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & CMS_BINARY)
|
||||
inmode = "rb";
|
||||
}
|
||||
|
||||
if (operation == SMIME_ENCRYPT)
|
||||
{
|
||||
if (!cipher)
|
||||
{
|
||||
#ifndef OPENSSL_NO_RC2
|
||||
cipher = EVP_rc2_40_cbc();
|
||||
#else
|
||||
BIO_printf(bio_err, "No cipher selected\n");
|
||||
goto end;
|
||||
#endif
|
||||
}
|
||||
encerts = sk_X509_new_null();
|
||||
while (*args)
|
||||
{
|
||||
if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
|
||||
NULL, e, "recipient certificate file")))
|
||||
{
|
||||
#if 0 /* An appropriate message is already printed */
|
||||
BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args);
|
||||
#endif
|
||||
goto end;
|
||||
}
|
||||
sk_X509_push(encerts, cert);
|
||||
cert = NULL;
|
||||
args++;
|
||||
}
|
||||
}
|
||||
|
||||
if (certfile)
|
||||
{
|
||||
if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
|
||||
e, "certificate file")))
|
||||
{
|
||||
ERR_print_errors(bio_err);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (recipfile && (operation == SMIME_DECRYPT))
|
||||
{
|
||||
if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
|
||||
e, "recipient certificate file")))
|
||||
{
|
||||
ERR_print_errors(bio_err);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation == SMIME_DECRYPT)
|
||||
{
|
||||
if (!keyfile)
|
||||
keyfile = recipfile;
|
||||
}
|
||||
else if (operation == SMIME_SIGN)
|
||||
{
|
||||
if (!keyfile)
|
||||
keyfile = signerfile;
|
||||
}
|
||||
else keyfile = NULL;
|
||||
|
||||
if (keyfile)
|
||||
{
|
||||
key = load_key(bio_err, keyfile, keyform, 0, passin, e,
|
||||
"signing key file");
|
||||
if (!key)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (infile)
|
||||
{
|
||||
if (!(in = BIO_new_file(infile, inmode)))
|
||||
{
|
||||
BIO_printf (bio_err,
|
||||
"Can't open input file %s\n", infile);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
in = BIO_new_fp(stdin, BIO_NOCLOSE);
|
||||
|
||||
if (operation & SMIME_IP)
|
||||
{
|
||||
if (informat == FORMAT_SMIME)
|
||||
cms = SMIME_read_CMS(in, &indata);
|
||||
else if (informat == FORMAT_PEM)
|
||||
cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
|
||||
else if (informat == FORMAT_ASN1)
|
||||
cms = d2i_CMS_bio(in, NULL);
|
||||
else
|
||||
{
|
||||
BIO_printf(bio_err, "Bad input format for CMS file\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!cms)
|
||||
{
|
||||
BIO_printf(bio_err, "Error reading S/MIME message\n");
|
||||
goto end;
|
||||
}
|
||||
if (contfile)
|
||||
{
|
||||
BIO_free(indata);
|
||||
if (!(indata = BIO_new_file(contfile, "rb")))
|
||||
{
|
||||
BIO_printf(bio_err, "Can't read content file %s\n", contfile);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outfile)
|
||||
{
|
||||
if (!(out = BIO_new_file(outfile, outmode)))
|
||||
{
|
||||
BIO_printf (bio_err,
|
||||
"Can't open output file %s\n", outfile);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out = BIO_new_fp(stdout, BIO_NOCLOSE);
|
||||
#ifdef OPENSSL_SYS_VMS
|
||||
{
|
||||
BIO *tmpbio = BIO_new(BIO_f_linebuffer());
|
||||
out = BIO_push(tmpbio, out);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (operation == SMIME_VERIFY)
|
||||
{
|
||||
if (!(store = setup_verify(bio_err, CAfile, CApath)))
|
||||
goto end;
|
||||
X509_STORE_set_verify_cb_func(store, smime_cb);
|
||||
if (vpm)
|
||||
X509_STORE_set1_param(store, vpm);
|
||||
}
|
||||
|
||||
|
||||
ret = 3;
|
||||
|
||||
if (operation == SMIME_DATA_CREATE)
|
||||
{
|
||||
if (indef)
|
||||
flags |= CMS_STREAM;
|
||||
cms = CMS_data_create(in, flags);
|
||||
}
|
||||
else if (operation == SMIME_DIGEST_CREATE)
|
||||
{
|
||||
if (indef)
|
||||
flags |= CMS_STREAM;
|
||||
cms = CMS_digest_create(in, sign_md, flags);
|
||||
}
|
||||
else if (operation == SMIME_COMPRESS)
|
||||
{
|
||||
if (indef)
|
||||
flags |= CMS_STREAM;
|
||||
cms = CMS_compress(in, -1, flags);
|
||||
}
|
||||
else if (operation == SMIME_ENCRYPT)
|
||||
{
|
||||
if (indef)
|
||||
flags |= CMS_STREAM;
|
||||
cms = CMS_encrypt(encerts, in, cipher, flags);
|
||||
}
|
||||
else if (operation & SMIME_SIGNERS)
|
||||
{
|
||||
int i;
|
||||
/* If detached data content we only enable streaming if
|
||||
* S/MIME output format.
|
||||
*/
|
||||
if (operation == SMIME_SIGN)
|
||||
{
|
||||
if (flags & CMS_DETACHED)
|
||||
{
|
||||
if (outformat == FORMAT_SMIME)
|
||||
flags |= CMS_STREAM;
|
||||
}
|
||||
else if (indef)
|
||||
flags |= CMS_STREAM;
|
||||
flags |= CMS_PARTIAL;
|
||||
cms = CMS_sign(NULL, NULL, other, in, flags);
|
||||
if (!cms)
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
flags |= CMS_REUSE_DIGEST;
|
||||
for (i = 0; i < sk_num(sksigners); i++)
|
||||
{
|
||||
signerfile = sk_value(sksigners, i);
|
||||
keyfile = sk_value(skkeys, i);
|
||||
signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL,
|
||||
e, "signer certificate");
|
||||
if (!signer)
|
||||
goto end;
|
||||
key = load_key(bio_err, keyfile, keyform, 0, passin, e,
|
||||
"signing key file");
|
||||
if (!key)
|
||||
goto end;
|
||||
if (!CMS_add1_signer(cms, signer, key, sign_md, flags))
|
||||
goto end;
|
||||
X509_free(signer);
|
||||
signer = NULL;
|
||||
EVP_PKEY_free(key);
|
||||
key = NULL;
|
||||
}
|
||||
/* If not streaming or resigning finalize structure */
|
||||
if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM))
|
||||
{
|
||||
if (!CMS_final(cms, in, flags))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cms)
|
||||
{
|
||||
BIO_printf(bio_err, "Error creating CMS structure\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 4;
|
||||
if (operation == SMIME_DECRYPT)
|
||||
{
|
||||
if (!CMS_decrypt(cms, key, recip, out, flags))
|
||||
{
|
||||
BIO_printf(bio_err, "Error decrypting CMS structure\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (operation == SMIME_DATAOUT)
|
||||
{
|
||||
if (!CMS_data(cms, out, flags))
|
||||
goto end;
|
||||
}
|
||||
else if (operation == SMIME_UNCOMPRESS)
|
||||
{
|
||||
if (!CMS_uncompress(cms, indata, out, flags))
|
||||
goto end;
|
||||
}
|
||||
else if (operation == SMIME_DIGEST_VERIFY)
|
||||
{
|
||||
if (CMS_digest_verify(cms, indata, out, flags) > 0)
|
||||
BIO_printf(bio_err, "Verification successful\n");
|
||||
else
|
||||
{
|
||||
BIO_printf(bio_err, "Verification failure\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (operation == SMIME_VERIFY)
|
||||
{
|
||||
if (CMS_verify(cms, other, store, indata, out, flags) > 0)
|
||||
BIO_printf(bio_err, "Verification successful\n");
|
||||
else
|
||||
{
|
||||
BIO_printf(bio_err, "Verification failure\n");
|
||||
goto end;
|
||||
}
|
||||
if (signerfile)
|
||||
{
|
||||
STACK_OF(X509) *signers;
|
||||
signers = CMS_get0_signers(cms);
|
||||
if (!save_certs(signerfile, signers))
|
||||
{
|
||||
BIO_printf(bio_err,
|
||||
"Error writing signers to %s\n",
|
||||
signerfile);
|
||||
ret = 5;
|
||||
goto end;
|
||||
}
|
||||
sk_X509_free(signers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outformat == FORMAT_SMIME)
|
||||
{
|
||||
if (to)
|
||||
BIO_printf(out, "To: %s\n", to);
|
||||
if (from)
|
||||
BIO_printf(out, "From: %s\n", from);
|
||||
if (subject)
|
||||
BIO_printf(out, "Subject: %s\n", subject);
|
||||
if (operation == SMIME_RESIGN)
|
||||
ret = SMIME_write_CMS(out, cms, indata, flags);
|
||||
else
|
||||
ret = SMIME_write_CMS(out, cms, in, flags);
|
||||
}
|
||||
else if (outformat == FORMAT_PEM)
|
||||
ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
|
||||
else if (outformat == FORMAT_ASN1)
|
||||
ret = i2d_CMS_bio_stream(out,cms, in, flags);
|
||||
else
|
||||
{
|
||||
BIO_printf(bio_err, "Bad output format for CMS file\n");
|
||||
goto end;
|
||||
}
|
||||
if (ret <= 0)
|
||||
{
|
||||
ret = 6;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
end:
|
||||
if (ret)
|
||||
ERR_print_errors(bio_err);
|
||||
if (need_rand)
|
||||
app_RAND_write_file(NULL, bio_err);
|
||||
sk_X509_pop_free(encerts, X509_free);
|
||||
sk_X509_pop_free(other, X509_free);
|
||||
if (vpm)
|
||||
X509_VERIFY_PARAM_free(vpm);
|
||||
if (sksigners)
|
||||
sk_free(sksigners);
|
||||
if (skkeys)
|
||||
sk_free(skkeys);
|
||||
X509_STORE_free(store);
|
||||
X509_free(cert);
|
||||
X509_free(recip);
|
||||
X509_free(signer);
|
||||
EVP_PKEY_free(key);
|
||||
CMS_ContentInfo_free(cms);
|
||||
BIO_free(in);
|
||||
BIO_free(indata);
|
||||
BIO_free_all(out);
|
||||
if (passin) OPENSSL_free(passin);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int save_certs(char *signerfile, STACK_OF(X509) *signers)
|
||||
{
|
||||
int i;
|
||||
BIO *tmp;
|
||||
if (!signerfile)
|
||||
return 1;
|
||||
tmp = BIO_new_file(signerfile, "w");
|
||||
if (!tmp) return 0;
|
||||
for(i = 0; i < sk_X509_num(signers); i++)
|
||||
PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
|
||||
BIO_free(tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Minimal callback just to output policy info (if any) */
|
||||
|
||||
static int smime_cb(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = X509_STORE_CTX_get_error(ctx);
|
||||
|
||||
if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
|
||||
&& ((error != X509_V_OK) || (ok != 2)))
|
||||
return ok;
|
||||
|
||||
policies_print(NULL, ctx);
|
||||
|
||||
return ok;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
34
apps/enc.c
34
apps/enc.c
@ -67,6 +67,7 @@
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/comp.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int set_hex(char *in,unsigned char *out,int size);
|
||||
@ -116,6 +117,10 @@ int MAIN(int argc, char **argv)
|
||||
char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
|
||||
char *md=NULL;
|
||||
int enc=1,printkey=0,i,base64=0;
|
||||
#ifdef ZLIB
|
||||
int do_zlib=0;
|
||||
BIO *bzl = NULL;
|
||||
#endif
|
||||
int debug=0,olb64=0,nosalt=0;
|
||||
const EVP_CIPHER *cipher=NULL,*c;
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
@ -141,9 +146,18 @@ int MAIN(int argc, char **argv)
|
||||
program_name(argv[0],pname,sizeof pname);
|
||||
if (strcmp(pname,"base64") == 0)
|
||||
base64=1;
|
||||
#ifdef ZLIB
|
||||
if (strcmp(pname,"zlib") == 0)
|
||||
do_zlib=1;
|
||||
#endif
|
||||
|
||||
cipher=EVP_get_cipherbyname(pname);
|
||||
#ifdef ZLIB
|
||||
if (!do_zlib && !base64 && (cipher == NULL)
|
||||
&& (strcmp(pname,"enc") != 0))
|
||||
#else
|
||||
if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0))
|
||||
#endif
|
||||
{
|
||||
BIO_printf(bio_err,"%s is an unknown cipher\n",pname);
|
||||
goto bad;
|
||||
@ -199,6 +213,10 @@ int MAIN(int argc, char **argv)
|
||||
base64=1;
|
||||
else if (strcmp(*argv,"-base64") == 0)
|
||||
base64=1;
|
||||
#ifdef ZLIB
|
||||
else if (strcmp(*argv,"-z") == 0)
|
||||
do_zlib=1;
|
||||
#endif
|
||||
else if (strcmp(*argv,"-bufsize") == 0)
|
||||
{
|
||||
if (--argc < 1) goto bad;
|
||||
@ -448,6 +466,19 @@ bad:
|
||||
rbio=in;
|
||||
wbio=out;
|
||||
|
||||
#ifdef ZLIB
|
||||
|
||||
if (do_zlib)
|
||||
{
|
||||
if ((bzl=BIO_new(BIO_f_zlib())) == NULL)
|
||||
goto end;
|
||||
if (enc)
|
||||
wbio=BIO_push(bzl,wbio);
|
||||
else
|
||||
rbio=BIO_push(bzl,rbio);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (base64)
|
||||
{
|
||||
if ((b64=BIO_new(BIO_f_base64())) == NULL)
|
||||
@ -641,6 +672,9 @@ end:
|
||||
if (out != NULL) BIO_free_all(out);
|
||||
if (benc != NULL) BIO_free(benc);
|
||||
if (b64 != NULL) BIO_free(b64);
|
||||
#ifdef ZLIB
|
||||
if (bzl != NULL) BIO_free(bzl);
|
||||
#endif
|
||||
if(pass) OPENSSL_free(pass);
|
||||
apps_shutdown();
|
||||
OPENSSL_EXIT(ret);
|
||||
|
@ -29,6 +29,7 @@ extern int speed_main(int argc,char *argv[]);
|
||||
extern int s_time_main(int argc,char *argv[]);
|
||||
extern int version_main(int argc,char *argv[]);
|
||||
extern int pkcs7_main(int argc,char *argv[]);
|
||||
extern int cms_main(int argc,char *argv[]);
|
||||
extern int crl2pkcs7_main(int argc,char *argv[]);
|
||||
extern int sess_id_main(int argc,char *argv[]);
|
||||
extern int ciphers_main(int argc,char *argv[]);
|
||||
@ -118,6 +119,9 @@ FUNCTION functions[] = {
|
||||
#endif
|
||||
{FUNC_TYPE_GENERAL,"version",version_main},
|
||||
{FUNC_TYPE_GENERAL,"pkcs7",pkcs7_main},
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
{FUNC_TYPE_GENERAL,"cms",cms_main},
|
||||
#endif
|
||||
{FUNC_TYPE_GENERAL,"crl2pkcs7",crl2pkcs7_main},
|
||||
{FUNC_TYPE_GENERAL,"sess_id",sess_id_main},
|
||||
#if !defined(OPENSSL_NO_SOCK) && !(defined(OPENSSL_NO_SSL2) && defined(OPENSSL_NO_SSL3))
|
||||
@ -198,6 +202,9 @@ FUNCTION functions[] = {
|
||||
{FUNC_TYPE_CIPHER,"camellia-256-ecb",enc_main},
|
||||
#endif
|
||||
{FUNC_TYPE_CIPHER,"base64",enc_main},
|
||||
#ifdef ZLIB
|
||||
{FUNC_TYPE_CIPHER,"zlib",enc_main},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DES
|
||||
{FUNC_TYPE_CIPHER,"des",enc_main},
|
||||
#endif
|
||||
|
@ -46,6 +46,8 @@ foreach (@ARGV)
|
||||
{ print "#ifndef OPENSSL_NO_DH\n${str}#endif\n"; }
|
||||
elsif ( ($_ =~ /^pkcs12$/))
|
||||
{ print "#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)\n${str}#endif\n"; }
|
||||
elsif ( ($_ =~ /^cms$/))
|
||||
{ print "#ifndef OPENSSL_NO_CMS\n${str}#endif\n"; }
|
||||
else
|
||||
{ print $str; }
|
||||
}
|
||||
@ -63,7 +65,7 @@ foreach (
|
||||
"camellia-128-cbc", "camellia-128-ecb",
|
||||
"camellia-192-cbc", "camellia-192-ecb",
|
||||
"camellia-256-cbc", "camellia-256-ecb",
|
||||
"base64",
|
||||
"base64", "zlib",
|
||||
"des", "des3", "desx", "idea", "seed", "rc4", "rc4-40",
|
||||
"rc2", "bf", "cast", "rc5",
|
||||
"des-ecb", "des-ede", "des-ede3",
|
||||
@ -90,6 +92,7 @@ foreach (
|
||||
elsif ($_ =~ /bf/) { $t="#ifndef OPENSSL_NO_BF\n${t}#endif\n"; }
|
||||
elsif ($_ =~ /cast/) { $t="#ifndef OPENSSL_NO_CAST\n${t}#endif\n"; }
|
||||
elsif ($_ =~ /rc5/) { $t="#ifndef OPENSSL_NO_RC5\n${t}#endif\n"; }
|
||||
elsif ($_ =~ /zlib/) { $t="#ifdef ZLIB\n${t}#endif\n"; }
|
||||
print $t;
|
||||
}
|
||||
|
||||
|
259
crypto/aes/aes_wrap.c
Normal file
259
crypto/aes/aes_wrap.c
Normal file
@ -0,0 +1,259 @@
|
||||
/* crypto/aes/aes_wrap.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/aes.h>
|
||||
#include <openssl/bio.h>
|
||||
|
||||
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
|
||||
unsigned char *out,
|
||||
const unsigned char *in, unsigned int inlen)
|
||||
{
|
||||
unsigned char *A, B[16], *R;
|
||||
unsigned int i, j, t;
|
||||
if ((inlen & 0x7) || (inlen < 8))
|
||||
return -1;
|
||||
A = B;
|
||||
t = 1;
|
||||
memcpy(out + 8, in, inlen);
|
||||
if (!iv)
|
||||
iv = default_iv;
|
||||
|
||||
memcpy(A, iv, 8);
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
R = out + 8;
|
||||
for (i = 0; i < inlen; i += 8, t++, R += 8)
|
||||
{
|
||||
memcpy(B + 8, R, 8);
|
||||
AES_encrypt(B, B, key);
|
||||
A[7] ^= (unsigned char)(t & 0xff);
|
||||
if (t > 0xff)
|
||||
{
|
||||
A[6] ^= (unsigned char)((t & 0xff) >> 8);
|
||||
A[5] ^= (unsigned char)((t & 0xff) >> 16);
|
||||
A[4] ^= (unsigned char)((t & 0xff) >> 24);
|
||||
}
|
||||
memcpy(R, B + 8, 8);
|
||||
}
|
||||
}
|
||||
memcpy(out, A, 8);
|
||||
return inlen + 8;
|
||||
}
|
||||
|
||||
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
|
||||
unsigned char *out,
|
||||
const unsigned char *in, unsigned int inlen)
|
||||
{
|
||||
unsigned char *A, B[16], *R;
|
||||
unsigned int i, j, t;
|
||||
inlen -= 8;
|
||||
if (inlen & 0x7)
|
||||
return -1;
|
||||
if (inlen < 8)
|
||||
return -1;
|
||||
A = B;
|
||||
t = 6 * (inlen >> 3);
|
||||
memcpy(A, in, 8);
|
||||
memcpy(out, in + 8, inlen);
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
R = out + inlen - 8;
|
||||
for (i = 0; i < inlen; i += 8, t--, R -= 8)
|
||||
{
|
||||
A[7] ^= (unsigned char)(t & 0xff);
|
||||
if (t > 0xff)
|
||||
{
|
||||
A[6] ^= (unsigned char)((t & 0xff) >> 8);
|
||||
A[5] ^= (unsigned char)((t & 0xff) >> 16);
|
||||
A[4] ^= (unsigned char)((t & 0xff) >> 24);
|
||||
}
|
||||
memcpy(B + 8, R, 8);
|
||||
AES_decrypt(B, B, key);
|
||||
memcpy(R, B + 8, 8);
|
||||
}
|
||||
}
|
||||
if (!iv)
|
||||
iv = default_iv;
|
||||
if (memcmp(A, iv, 8))
|
||||
{
|
||||
OPENSSL_cleanse(out, inlen);
|
||||
return 0;
|
||||
}
|
||||
return inlen;
|
||||
}
|
||||
|
||||
#ifdef AES_WRAP_TEST
|
||||
|
||||
int AES_wrap_unwrap_test(const unsigned char *kek, int keybits,
|
||||
const unsigned char *iv,
|
||||
const unsigned char *eout,
|
||||
const unsigned char *key, int keylen)
|
||||
{
|
||||
unsigned char *otmp = NULL, *ptmp = NULL;
|
||||
int r, ret = 0;
|
||||
AES_KEY wctx;
|
||||
otmp = OPENSSL_malloc(keylen + 8);
|
||||
ptmp = OPENSSL_malloc(keylen);
|
||||
if (!otmp || !ptmp)
|
||||
return 0;
|
||||
if (AES_set_encrypt_key(kek, keybits, &wctx))
|
||||
goto err;
|
||||
r = AES_wrap_key(&wctx, iv, otmp, key, keylen);
|
||||
if (r <= 0)
|
||||
goto err;
|
||||
|
||||
if (eout && memcmp(eout, otmp, keylen))
|
||||
goto err;
|
||||
|
||||
if (AES_set_decrypt_key(kek, keybits, &wctx))
|
||||
goto err;
|
||||
r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r);
|
||||
|
||||
if (memcmp(key, ptmp, keylen))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (otmp)
|
||||
OPENSSL_free(otmp);
|
||||
if (ptmp)
|
||||
OPENSSL_free(ptmp);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
static const unsigned char kek[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
||||
};
|
||||
|
||||
static const unsigned char key[] = {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
||||
};
|
||||
|
||||
static const unsigned char default_iv[] = {
|
||||
0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
|
||||
};
|
||||
|
||||
static const unsigned char e1[] = {
|
||||
0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47,
|
||||
0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82,
|
||||
0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5
|
||||
};
|
||||
|
||||
static const unsigned char e2[] = {
|
||||
0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35,
|
||||
0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2,
|
||||
0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d
|
||||
};
|
||||
|
||||
static const unsigned char e3[] = {
|
||||
0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2,
|
||||
0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a,
|
||||
0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7
|
||||
};
|
||||
|
||||
static const unsigned char e4[] = {
|
||||
0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32,
|
||||
0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc,
|
||||
0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93,
|
||||
0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2
|
||||
};
|
||||
|
||||
static const unsigned char e5[] = {
|
||||
0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f,
|
||||
0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4,
|
||||
0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95,
|
||||
0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1
|
||||
};
|
||||
|
||||
static const unsigned char e6[] = {
|
||||
0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4,
|
||||
0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26,
|
||||
0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26,
|
||||
0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b,
|
||||
0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21
|
||||
};
|
||||
|
||||
AES_KEY wctx, xctx;
|
||||
int ret;
|
||||
ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16);
|
||||
fprintf(stderr, "Key test result %d\n", ret);
|
||||
ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16);
|
||||
fprintf(stderr, "Key test result %d\n", ret);
|
||||
ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16);
|
||||
fprintf(stderr, "Key test result %d\n", ret);
|
||||
ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24);
|
||||
fprintf(stderr, "Key test result %d\n", ret);
|
||||
ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24);
|
||||
fprintf(stderr, "Key test result %d\n", ret);
|
||||
ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32);
|
||||
fprintf(stderr, "Key test result %d\n", ret);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -27,7 +27,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \
|
||||
tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \
|
||||
tasn_prn.c ameth_lib.c \
|
||||
f_int.c f_string.c n_pkey.c \
|
||||
f_enum.c x_pkey.c a_bool.c x_exten.c bio_asn1.c \
|
||||
f_enum.c x_pkey.c a_bool.c x_exten.c bio_asn1.c bio_ndef.c asn_mime.c \
|
||||
asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_bytes.c a_strnid.c \
|
||||
evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c
|
||||
LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \
|
||||
@ -40,7 +40,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \
|
||||
tasn_new.o tasn_fre.o tasn_enc.o tasn_dec.o tasn_utl.o tasn_typ.o \
|
||||
tasn_prn.o ameth_lib.o \
|
||||
f_int.o f_string.o n_pkey.o \
|
||||
f_enum.o x_pkey.o a_bool.o x_exten.o bio_asn1.o \
|
||||
f_enum.o x_pkey.o a_bool.o x_exten.o bio_asn1.o bio_ndef.o asn_mime.o \
|
||||
asn1_gen.o asn1_par.o asn1_lib.o asn1_err.o a_bytes.o a_strnid.o \
|
||||
evp_asn1.o asn_pack.o p5_pbe.o p5_pbev2.o p8_pkey.o asn_moid.o
|
||||
|
||||
@ -366,6 +366,20 @@ asn1_par.o: ../../include/openssl/opensslconf.h
|
||||
asn1_par.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
asn1_par.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
|
||||
asn1_par.o: ../../include/openssl/symhacks.h ../cryptlib.h asn1_par.c
|
||||
asn_mime.o: ../../e_os.h ../../include/openssl/asn1.h
|
||||
asn_mime.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
|
||||
asn_mime.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
|
||||
asn_mime.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
|
||||
asn_mime.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
|
||||
asn_mime.o: ../../include/openssl/err.h ../../include/openssl/evp.h
|
||||
asn_mime.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
asn_mime.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
|
||||
asn_mime.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
asn_mime.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
|
||||
asn_mime.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
|
||||
asn_mime.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
|
||||
asn_mime.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
|
||||
asn_mime.o: ../cryptlib.h asn1_locl.h asn_mime.c
|
||||
asn_moid.o: ../../e_os.h ../../include/openssl/asn1.h
|
||||
asn_moid.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
|
||||
asn_moid.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
|
||||
@ -394,16 +408,26 @@ bio_asn1.o: ../../include/openssl/opensslconf.h
|
||||
bio_asn1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
bio_asn1.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
|
||||
bio_asn1.o: ../../include/openssl/symhacks.h bio_asn1.c
|
||||
bio_ndef.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
|
||||
bio_ndef.o: ../../include/openssl/bio.h ../../include/openssl/crypto.h
|
||||
bio_ndef.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
|
||||
bio_ndef.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h
|
||||
bio_ndef.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
bio_ndef.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
|
||||
bio_ndef.o: ../../include/openssl/symhacks.h bio_ndef.c
|
||||
d2i_pr.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
|
||||
d2i_pr.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
|
||||
d2i_pr.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
|
||||
d2i_pr.o: ../../include/openssl/engine.h ../../include/openssl/err.h
|
||||
d2i_pr.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
|
||||
d2i_pr.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
|
||||
d2i_pr.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
|
||||
d2i_pr.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h
|
||||
d2i_pr.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
|
||||
d2i_pr.o: ../cryptlib.h asn1_locl.h d2i_pr.c
|
||||
d2i_pr.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
|
||||
d2i_pr.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
|
||||
d2i_pr.o: ../../include/openssl/err.h ../../include/openssl/evp.h
|
||||
d2i_pr.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
d2i_pr.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
|
||||
d2i_pr.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
d2i_pr.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
|
||||
d2i_pr.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
d2i_pr.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
|
||||
d2i_pr.o: ../../include/openssl/x509_vfy.h ../cryptlib.h asn1_locl.h d2i_pr.c
|
||||
d2i_pu.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
|
||||
d2i_pu.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
|
||||
d2i_pu.o: ../../include/openssl/crypto.h ../../include/openssl/dsa.h
|
||||
@ -447,13 +471,16 @@ f_string.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
|
||||
f_string.o: ../../include/openssl/symhacks.h ../cryptlib.h f_string.c
|
||||
i2d_pr.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
|
||||
i2d_pr.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
|
||||
i2d_pr.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
|
||||
i2d_pr.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
|
||||
i2d_pr.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
|
||||
i2d_pr.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
|
||||
i2d_pr.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h
|
||||
i2d_pr.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
|
||||
i2d_pr.o: ../cryptlib.h asn1_locl.h i2d_pr.c
|
||||
i2d_pr.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
|
||||
i2d_pr.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
|
||||
i2d_pr.o: ../../include/openssl/err.h ../../include/openssl/evp.h
|
||||
i2d_pr.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
i2d_pr.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
|
||||
i2d_pr.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
i2d_pr.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
|
||||
i2d_pr.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
i2d_pr.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
|
||||
i2d_pr.o: ../../include/openssl/x509_vfy.h ../cryptlib.h asn1_locl.h i2d_pr.c
|
||||
i2d_pu.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
|
||||
i2d_pu.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
|
||||
i2d_pu.o: ../../include/openssl/crypto.h ../../include/openssl/dsa.h
|
||||
|
@ -158,7 +158,12 @@ extern "C" {
|
||||
#define MBSTRING_BMP (MBSTRING_FLAG|2)
|
||||
#define MBSTRING_UNIV (MBSTRING_FLAG|4)
|
||||
|
||||
#define SMIME_OLDMIME 0x400
|
||||
#define SMIME_CRLFEOL 0x800
|
||||
#define SMIME_STREAM 0x1000
|
||||
|
||||
struct X509_algor_st;
|
||||
DECLARE_STACK_OF(X509_ALGOR)
|
||||
|
||||
#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
|
||||
#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
|
||||
@ -218,6 +223,13 @@ typedef struct asn1_object_st
|
||||
* be inserted in the memory buffer
|
||||
*/
|
||||
#define ASN1_STRING_FLAG_NDEF 0x010
|
||||
|
||||
/* This flag is used by the CMS code to indicate that a string is not
|
||||
* complete and is a place holder for content when it had all been
|
||||
* accessed. The flag will be reset when content has been written to it.
|
||||
*/
|
||||
|
||||
#define ASN1_STRING_FLAG_CONT 0x020
|
||||
/* This is the base type that holds just about everything :-) */
|
||||
typedef struct asn1_string_st
|
||||
{
|
||||
@ -939,6 +951,12 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
|
||||
|
||||
void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
|
||||
|
||||
/* ASN1 alloc/free macros for when a type is only used internally */
|
||||
|
||||
#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
|
||||
#define M_ASN1_free_of(x, type) \
|
||||
ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
|
||||
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
|
||||
|
||||
@ -1100,6 +1118,21 @@ void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
|
||||
|
||||
BIO_METHOD *BIO_f_asn1(void);
|
||||
|
||||
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
|
||||
|
||||
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const ASN1_ITEM *it);
|
||||
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const char *hdr,
|
||||
const ASN1_ITEM *it);
|
||||
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
|
||||
int ctype_nid,
|
||||
STACK_OF(X509_ALGOR) *mdalgs,
|
||||
const ASN1_ITEM *it);
|
||||
ASN1_VALUE *SMIME_read_asn1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
|
||||
int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
|
||||
int SMIME_text(BIO *in, BIO *out);
|
||||
|
||||
/* 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.
|
||||
@ -1149,6 +1182,7 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_F_ASN1_ITEM_VERIFY 197
|
||||
#define ASN1_F_ASN1_MBSTRING_NCOPY 122
|
||||
#define ASN1_F_ASN1_OBJECT_NEW 123
|
||||
#define ASN1_F_ASN1_OUTPUT_DATA 214
|
||||
#define ASN1_F_ASN1_PACK_STRING 124
|
||||
#define ASN1_F_ASN1_PCTX_NEW 205
|
||||
#define ASN1_F_ASN1_PKCS5_PBE_SET 125
|
||||
@ -1168,6 +1202,9 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_F_ASN1_UNPACK_STRING 136
|
||||
#define ASN1_F_ASN1_UTCTIME_SET 187
|
||||
#define ASN1_F_ASN1_VERIFY 137
|
||||
#define ASN1_F_B64_READ_ASN1 209
|
||||
#define ASN1_F_B64_WRITE_ASN1 210
|
||||
#define ASN1_F_BIO_NEW_NDEF 208
|
||||
#define ASN1_F_BITSTR_CB 180
|
||||
#define ASN1_F_BN_TO_ASN1_ENUMERATED 138
|
||||
#define ASN1_F_BN_TO_ASN1_INTEGER 139
|
||||
@ -1196,6 +1233,7 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_F_D2I_X509 156
|
||||
#define ASN1_F_D2I_X509_CINF 157
|
||||
#define ASN1_F_D2I_X509_PKEY 159
|
||||
#define ASN1_F_I2D_ASN1_BIO_STREAM 211
|
||||
#define ASN1_F_I2D_ASN1_SET 188
|
||||
#define ASN1_F_I2D_ASN1_TIME 160
|
||||
#define ASN1_F_I2D_DSA_PUBKEY 161
|
||||
@ -1209,6 +1247,9 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_F_PARSE_TAGGING 182
|
||||
#define ASN1_F_PKCS5_PBE2_SET_IV 167
|
||||
#define ASN1_F_PKCS5_PBE_SET 202
|
||||
#define ASN1_F_PKCS5_PBE_SET0_ALGOR 215
|
||||
#define ASN1_F_SMIME_READ_ASN1 212
|
||||
#define ASN1_F_SMIME_TEXT 213
|
||||
#define ASN1_F_X509_CINF_NEW 168
|
||||
#define ASN1_F_X509_CRL_ADD0_REVOKED 169
|
||||
#define ASN1_F_X509_INFO_NEW 170
|
||||
@ -1220,6 +1261,8 @@ void ERR_load_ASN1_strings(void);
|
||||
|
||||
/* Reason codes. */
|
||||
#define ASN1_R_ADDING_OBJECT 171
|
||||
#define ASN1_R_ASN1_PARSE_ERROR 203
|
||||
#define ASN1_R_ASN1_SIG_PARSE_ERROR 204
|
||||
#define ASN1_R_AUX_ERROR 100
|
||||
#define ASN1_R_BAD_CLASS 101
|
||||
#define ASN1_R_BAD_OBJECT_HEADER 102
|
||||
@ -1267,6 +1310,7 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128
|
||||
#define ASN1_R_INVALID_BMPSTRING_LENGTH 129
|
||||
#define ASN1_R_INVALID_DIGIT 130
|
||||
#define ASN1_R_INVALID_MIME_TYPE 205
|
||||
#define ASN1_R_INVALID_MODIFIER 186
|
||||
#define ASN1_R_INVALID_NUMBER 187
|
||||
#define ASN1_R_INVALID_SEPARATOR 131
|
||||
@ -1276,6 +1320,9 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_R_IV_TOO_LARGE 135
|
||||
#define ASN1_R_LENGTH_ERROR 136
|
||||
#define ASN1_R_LIST_ERROR 188
|
||||
#define ASN1_R_MIME_NO_CONTENT_TYPE 206
|
||||
#define ASN1_R_MIME_PARSE_ERROR 207
|
||||
#define ASN1_R_MIME_SIG_PARSE_ERROR 208
|
||||
#define ASN1_R_MISSING_EOC 137
|
||||
#define ASN1_R_MISSING_SECOND_NUMBER 138
|
||||
#define ASN1_R_MISSING_VALUE 189
|
||||
@ -1285,8 +1332,12 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_R_NON_HEX_CHARACTERS 141
|
||||
#define ASN1_R_NOT_ASCII_FORMAT 190
|
||||
#define ASN1_R_NOT_ENOUGH_DATA 142
|
||||
#define ASN1_R_NO_CONTENT_TYPE 209
|
||||
#define ASN1_R_NO_DEFAULT_DIGEST 201
|
||||
#define ASN1_R_NO_MATCHING_CHOICE_TYPE 143
|
||||
#define ASN1_R_NO_MULTIPART_BODY_FAILURE 210
|
||||
#define ASN1_R_NO_MULTIPART_BOUNDARY 211
|
||||
#define ASN1_R_NO_SIG_CONTENT_TYPE 212
|
||||
#define ASN1_R_NULL_IS_WRONG_LENGTH 144
|
||||
#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191
|
||||
#define ASN1_R_ODD_NUMBER_OF_CHARS 145
|
||||
@ -1296,6 +1347,8 @@ void ERR_load_ASN1_strings(void);
|
||||
#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149
|
||||
#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192
|
||||
#define ASN1_R_SHORT_LINE 150
|
||||
#define ASN1_R_SIG_INVALID_MIME_TYPE 213
|
||||
#define ASN1_R_STREAMING_NOT_SUPPORTED 202
|
||||
#define ASN1_R_STRING_TOO_LONG 151
|
||||
#define ASN1_R_STRING_TOO_SHORT 152
|
||||
#define ASN1_R_TAG_VALUE_TOO_HIGH 153
|
||||
|
@ -110,6 +110,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
|
||||
{ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY), "ASN1_item_verify"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW), "ASN1_OBJECT_new"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_OUTPUT_DATA), "ASN1_OUTPUT_DATA"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_PACK_STRING), "ASN1_pack_string"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_PCTX_NEW), "ASN1_PCTX_new"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_PKCS5_PBE_SET), "ASN1_PKCS5_PBE_SET"},
|
||||
@ -129,6 +130,9 @@ static ERR_STRING_DATA ASN1_str_functs[]=
|
||||
{ERR_FUNC(ASN1_F_ASN1_UNPACK_STRING), "ASN1_unpack_string"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_UTCTIME_SET), "ASN1_UTCTIME_set"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_VERIFY), "ASN1_verify"},
|
||||
{ERR_FUNC(ASN1_F_B64_READ_ASN1), "B64_READ_ASN1"},
|
||||
{ERR_FUNC(ASN1_F_B64_WRITE_ASN1), "B64_WRITE_ASN1"},
|
||||
{ERR_FUNC(ASN1_F_BIO_NEW_NDEF), "BIO_new_NDEF"},
|
||||
{ERR_FUNC(ASN1_F_BITSTR_CB), "BITSTR_CB"},
|
||||
{ERR_FUNC(ASN1_F_BN_TO_ASN1_ENUMERATED), "BN_to_ASN1_ENUMERATED"},
|
||||
{ERR_FUNC(ASN1_F_BN_TO_ASN1_INTEGER), "BN_to_ASN1_INTEGER"},
|
||||
@ -157,6 +161,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
|
||||
{ERR_FUNC(ASN1_F_D2I_X509), "D2I_X509"},
|
||||
{ERR_FUNC(ASN1_F_D2I_X509_CINF), "D2I_X509_CINF"},
|
||||
{ERR_FUNC(ASN1_F_D2I_X509_PKEY), "d2i_X509_PKEY"},
|
||||
{ERR_FUNC(ASN1_F_I2D_ASN1_BIO_STREAM), "i2d_ASN1_bio_stream"},
|
||||
{ERR_FUNC(ASN1_F_I2D_ASN1_SET), "i2d_ASN1_SET"},
|
||||
{ERR_FUNC(ASN1_F_I2D_ASN1_TIME), "I2D_ASN1_TIME"},
|
||||
{ERR_FUNC(ASN1_F_I2D_DSA_PUBKEY), "i2d_DSA_PUBKEY"},
|
||||
@ -170,6 +175,9 @@ static ERR_STRING_DATA ASN1_str_functs[]=
|
||||
{ERR_FUNC(ASN1_F_PARSE_TAGGING), "PARSE_TAGGING"},
|
||||
{ERR_FUNC(ASN1_F_PKCS5_PBE2_SET_IV), "PKCS5_pbe2_set_iv"},
|
||||
{ERR_FUNC(ASN1_F_PKCS5_PBE_SET), "PKCS5_pbe_set"},
|
||||
{ERR_FUNC(ASN1_F_PKCS5_PBE_SET0_ALGOR), "PKCS5_pbe_set0_algor"},
|
||||
{ERR_FUNC(ASN1_F_SMIME_READ_ASN1), "SMIME_read_asn1"},
|
||||
{ERR_FUNC(ASN1_F_SMIME_TEXT), "SMIME_text"},
|
||||
{ERR_FUNC(ASN1_F_X509_CINF_NEW), "X509_CINF_NEW"},
|
||||
{ERR_FUNC(ASN1_F_X509_CRL_ADD0_REVOKED), "X509_CRL_add0_revoked"},
|
||||
{ERR_FUNC(ASN1_F_X509_INFO_NEW), "X509_INFO_new"},
|
||||
@ -184,6 +192,8 @@ static ERR_STRING_DATA ASN1_str_functs[]=
|
||||
static ERR_STRING_DATA ASN1_str_reasons[]=
|
||||
{
|
||||
{ERR_REASON(ASN1_R_ADDING_OBJECT) ,"adding object"},
|
||||
{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR) ,"asn1 parse error"},
|
||||
{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR) ,"asn1 sig parse error"},
|
||||
{ERR_REASON(ASN1_R_AUX_ERROR) ,"aux error"},
|
||||
{ERR_REASON(ASN1_R_BAD_CLASS) ,"bad class"},
|
||||
{ERR_REASON(ASN1_R_BAD_OBJECT_HEADER) ,"bad object header"},
|
||||
@ -231,6 +241,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
|
||||
{ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),"integer too large for long"},
|
||||
{ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH),"invalid bmpstring length"},
|
||||
{ERR_REASON(ASN1_R_INVALID_DIGIT) ,"invalid digit"},
|
||||
{ERR_REASON(ASN1_R_INVALID_MIME_TYPE) ,"invalid mime type"},
|
||||
{ERR_REASON(ASN1_R_INVALID_MODIFIER) ,"invalid modifier"},
|
||||
{ERR_REASON(ASN1_R_INVALID_NUMBER) ,"invalid number"},
|
||||
{ERR_REASON(ASN1_R_INVALID_SEPARATOR) ,"invalid separator"},
|
||||
@ -240,6 +251,9 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
|
||||
{ERR_REASON(ASN1_R_IV_TOO_LARGE) ,"iv too large"},
|
||||
{ERR_REASON(ASN1_R_LENGTH_ERROR) ,"length error"},
|
||||
{ERR_REASON(ASN1_R_LIST_ERROR) ,"list error"},
|
||||
{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE) ,"mime no content type"},
|
||||
{ERR_REASON(ASN1_R_MIME_PARSE_ERROR) ,"mime parse error"},
|
||||
{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR) ,"mime sig parse error"},
|
||||
{ERR_REASON(ASN1_R_MISSING_EOC) ,"missing eoc"},
|
||||
{ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER),"missing second number"},
|
||||
{ERR_REASON(ASN1_R_MISSING_VALUE) ,"missing value"},
|
||||
@ -249,8 +263,12 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
|
||||
{ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) ,"non hex characters"},
|
||||
{ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) ,"not ascii format"},
|
||||
{ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) ,"not enough data"},
|
||||
{ERR_REASON(ASN1_R_NO_CONTENT_TYPE) ,"no content type"},
|
||||
{ERR_REASON(ASN1_R_NO_DEFAULT_DIGEST) ,"no default digest"},
|
||||
{ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE),"no matching choice type"},
|
||||
{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE),"no multipart body failure"},
|
||||
{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY),"no multipart boundary"},
|
||||
{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE) ,"no sig content type"},
|
||||
{ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) ,"null is wrong length"},
|
||||
{ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT),"object not ascii format"},
|
||||
{ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS) ,"odd number of chars"},
|
||||
@ -260,6 +278,8 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
|
||||
{ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED),"sequence not constructed"},
|
||||
{ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),"sequence or set needs config"},
|
||||
{ERR_REASON(ASN1_R_SHORT_LINE) ,"short line"},
|
||||
{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE),"sig invalid mime type"},
|
||||
{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED),"streaming not supported"},
|
||||
{ERR_REASON(ASN1_R_STRING_TOO_LONG) ,"string too long"},
|
||||
{ERR_REASON(ASN1_R_STRING_TOO_SHORT) ,"string too short"},
|
||||
{ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH) ,"tag value too high"},
|
||||
|
@ -169,6 +169,9 @@ extern "C" {
|
||||
#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)
|
||||
@ -215,6 +218,18 @@ extern "C" {
|
||||
#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:
|
||||
*
|
||||
@ -720,6 +735,16 @@ typedef struct ASN1_PRINT_ARG_st {
|
||||
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 */
|
||||
@ -741,6 +766,10 @@ typedef struct ASN1_PRINT_ARG_st {
|
||||
#define ASN1_OP_I2D_POST 7
|
||||
#define ASN1_OP_PRINT_PRE 8
|
||||
#define ASN1_OP_PRINT_POST 9
|
||||
#define ASN1_OP_STREAM_PRE 8
|
||||
#define ASN1_OP_STREAM_POST 9
|
||||
#define ASN1_OP_DETACHED_PRE 10
|
||||
#define ASN1_OP_DETACHED_POST 11
|
||||
|
||||
/* Macro to implement a primitive type */
|
||||
#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
|
||||
|
938
crypto/asn1/asn_mime.c
Normal file
938
crypto/asn1/asn_mime.c
Normal file
@ -0,0 +1,938 @@
|
||||
/* asn_mime.c */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-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 <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* Generalised MIME like utilities for streaming ASN1. Although many
|
||||
* have a PKCS7/CMS like flavour others are more general purpose.
|
||||
*/
|
||||
|
||||
/* MIME format structures
|
||||
* Note that all are translated to lower case apart from
|
||||
* parameter values. Quotes are stripped off
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *param_name; /* Param name e.g. "micalg" */
|
||||
char *param_value; /* Param value e.g. "sha1" */
|
||||
} MIME_PARAM;
|
||||
|
||||
DECLARE_STACK_OF(MIME_PARAM)
|
||||
IMPLEMENT_STACK_OF(MIME_PARAM)
|
||||
|
||||
typedef struct {
|
||||
char *name; /* Name of line e.g. "content-type" */
|
||||
char *value; /* Value of line e.g. "text/plain" */
|
||||
STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */
|
||||
} MIME_HEADER;
|
||||
|
||||
DECLARE_STACK_OF(MIME_HEADER)
|
||||
IMPLEMENT_STACK_OF(MIME_HEADER)
|
||||
|
||||
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
|
||||
const ASN1_ITEM *it);
|
||||
static char * strip_ends(char *name);
|
||||
static char * strip_start(char *name);
|
||||
static char * strip_end(char *name);
|
||||
static MIME_HEADER *mime_hdr_new(char *name, char *value);
|
||||
static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value);
|
||||
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
|
||||
static int mime_hdr_cmp(const MIME_HEADER * const *a,
|
||||
const MIME_HEADER * const *b);
|
||||
static int mime_param_cmp(const MIME_PARAM * const *a,
|
||||
const MIME_PARAM * const *b);
|
||||
static void mime_param_free(MIME_PARAM *param);
|
||||
static int mime_bound_check(char *line, int linelen, char *bound, int blen);
|
||||
static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
|
||||
static int strip_eol(char *linebuf, int *plen);
|
||||
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name);
|
||||
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name);
|
||||
static void mime_hdr_free(MIME_HEADER *hdr);
|
||||
|
||||
#define MAX_SMLEN 1024
|
||||
#define mime_debug(x) /* x */
|
||||
|
||||
/* Output an ASN1 structure in BER format streaming if necessary */
|
||||
|
||||
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
/* If streaming create stream BIO and copy all content through it */
|
||||
if (flags & SMIME_STREAM)
|
||||
{
|
||||
BIO *bio, *tbio;
|
||||
bio = BIO_new_NDEF(out, val, it);
|
||||
if (!bio)
|
||||
{
|
||||
ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM,ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
SMIME_crlf_copy(in, bio, flags);
|
||||
(void)BIO_flush(bio);
|
||||
/* Free up successive BIOs until we hit the old output BIO */
|
||||
do
|
||||
{
|
||||
tbio = BIO_pop(bio);
|
||||
BIO_free(bio);
|
||||
bio = tbio;
|
||||
} while (bio != out);
|
||||
}
|
||||
/* else just write out ASN1 structure which will have all content
|
||||
* stored internally
|
||||
*/
|
||||
else
|
||||
ASN1_item_i2d_bio(it, out, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Base 64 read and write of ASN1 structure */
|
||||
|
||||
static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *b64;
|
||||
int r;
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
if(!b64)
|
||||
{
|
||||
ASN1err(ASN1_F_B64_WRITE_ASN1,ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
/* prepend the b64 BIO so all data is base64 encoded.
|
||||
*/
|
||||
out = BIO_push(b64, out);
|
||||
r = i2d_ASN1_bio_stream(out, val, in, flags, it);
|
||||
(void)BIO_flush(out);
|
||||
BIO_pop(out);
|
||||
BIO_free(b64);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Streaming ASN1 PEM write */
|
||||
|
||||
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||
const char *hdr,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
int r;
|
||||
BIO_printf(out, "-----BEGIN %s-----\n", hdr);
|
||||
r = B64_write_ASN1(out, val, in, flags, it);
|
||||
BIO_printf(out, "-----END %s-----\n", hdr);
|
||||
return r;
|
||||
}
|
||||
|
||||
static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *b64;
|
||||
ASN1_VALUE *val;
|
||||
if(!(b64 = BIO_new(BIO_f_base64()))) {
|
||||
ASN1err(ASN1_F_B64_READ_ASN1,ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
bio = BIO_push(b64, bio);
|
||||
val = ASN1_item_d2i_bio(it, bio, NULL);
|
||||
if(!val)
|
||||
ASN1err(ASN1_F_B64_READ_ASN1,ASN1_R_DECODE_ERROR);
|
||||
(void)BIO_flush(bio);
|
||||
bio = BIO_pop(bio);
|
||||
BIO_free(b64);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
|
||||
|
||||
static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
int i, have_unknown = 0, write_comma, ret = 0, md_nid;
|
||||
have_unknown = 0;
|
||||
write_comma = 0;
|
||||
for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++)
|
||||
{
|
||||
if (write_comma)
|
||||
BIO_write(out, ",", 1);
|
||||
write_comma = 1;
|
||||
md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
|
||||
md = EVP_get_digestbynid(md_nid);
|
||||
if (md && md->md_ctrl)
|
||||
{
|
||||
int rv;
|
||||
char *micstr;
|
||||
rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr);
|
||||
if (rv > 0)
|
||||
{
|
||||
BIO_puts(out, micstr);
|
||||
OPENSSL_free(micstr);
|
||||
continue;
|
||||
}
|
||||
if (rv != -2)
|
||||
goto err;
|
||||
}
|
||||
switch(md_nid)
|
||||
{
|
||||
case NID_sha1:
|
||||
BIO_puts(out, "sha1");
|
||||
break;
|
||||
|
||||
case NID_md5:
|
||||
BIO_puts(out, "md5");
|
||||
break;
|
||||
|
||||
case NID_sha256:
|
||||
BIO_puts(out, "sha-256");
|
||||
break;
|
||||
|
||||
case NID_sha384:
|
||||
BIO_puts(out, "sha-384");
|
||||
break;
|
||||
|
||||
case NID_sha512:
|
||||
BIO_puts(out, "sha-512");
|
||||
break;
|
||||
|
||||
case NID_id_GostR3411_94:
|
||||
BIO_puts(out, "gostr3411-94");
|
||||
goto err;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (have_unknown)
|
||||
write_comma = 0;
|
||||
else
|
||||
{
|
||||
BIO_puts(out, "unknown");
|
||||
have_unknown = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* SMIME sender */
|
||||
|
||||
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
|
||||
int ctype_nid,
|
||||
STACK_OF(X509_ALGOR) *mdalgs,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
char bound[33], c;
|
||||
int i;
|
||||
const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
|
||||
const char *msg_type=NULL;
|
||||
if (flags & SMIME_OLDMIME)
|
||||
mime_prefix = "application/x-pkcs7-";
|
||||
else
|
||||
mime_prefix = "application/pkcs7-";
|
||||
|
||||
if (flags & SMIME_CRLFEOL)
|
||||
mime_eol = "\r\n";
|
||||
else
|
||||
mime_eol = "\n";
|
||||
if((flags & SMIME_DETACHED) && data) {
|
||||
/* We want multipart/signed */
|
||||
/* Generate a random boundary */
|
||||
RAND_pseudo_bytes((unsigned char *)bound, 32);
|
||||
for(i = 0; i < 32; i++) {
|
||||
c = bound[i] & 0xf;
|
||||
if(c < 10) c += '0';
|
||||
else c += 'A' - 10;
|
||||
bound[i] = c;
|
||||
}
|
||||
bound[32] = 0;
|
||||
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Type: multipart/signed;");
|
||||
BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
|
||||
BIO_puts(bio, " micalg=\"");
|
||||
asn1_write_micalg(bio, mdalgs);
|
||||
BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
|
||||
bound, mime_eol, mime_eol);
|
||||
BIO_printf(bio, "This is an S/MIME signed message%s%s",
|
||||
mime_eol, mime_eol);
|
||||
/* Now write out the first part */
|
||||
BIO_printf(bio, "------%s%s", bound, mime_eol);
|
||||
if (!asn1_output_data(bio, data, val, flags, it))
|
||||
return 0;
|
||||
BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
|
||||
|
||||
/* Headers for signature */
|
||||
|
||||
BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
|
||||
BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Transfer-Encoding: base64%s",
|
||||
mime_eol);
|
||||
BIO_printf(bio, "Content-Disposition: attachment;");
|
||||
BIO_printf(bio, " filename=\"smime.p7s\"%s%s",
|
||||
mime_eol, mime_eol);
|
||||
B64_write_ASN1(bio, val, NULL, 0, it);
|
||||
BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound,
|
||||
mime_eol, mime_eol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Determine smime-type header */
|
||||
|
||||
if (ctype_nid == NID_pkcs7_enveloped)
|
||||
msg_type = "enveloped-data";
|
||||
else if (ctype_nid == NID_pkcs7_signed)
|
||||
{
|
||||
if (sk_X509_ALGOR_num(mdalgs) >= 0)
|
||||
msg_type = "signed-data";
|
||||
else
|
||||
msg_type = "certs-only";
|
||||
}
|
||||
else if (ctype_nid == NID_id_smime_ct_compressedData)
|
||||
{
|
||||
msg_type = "compressed-data";
|
||||
cname = "smime.p7z";
|
||||
}
|
||||
/* MIME headers */
|
||||
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Disposition: attachment;");
|
||||
BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
|
||||
BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
|
||||
if (msg_type)
|
||||
BIO_printf(bio, " smime-type=%s;", msg_type);
|
||||
BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
|
||||
BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
|
||||
mime_eol, mime_eol);
|
||||
if (!B64_write_ASN1(bio, val, data, flags, it))
|
||||
return 0;
|
||||
BIO_printf(bio, "%s", mime_eol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle output of ASN1 data */
|
||||
|
||||
|
||||
static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *tmpbio;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!(flags & SMIME_DETACHED))
|
||||
{
|
||||
SMIME_crlf_copy(data, out, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!aux || !aux->asn1_cb)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_OUTPUT_DATA,
|
||||
ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
|
||||
/* Let ASN1 code prepend any needed BIOs */
|
||||
|
||||
if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0)
|
||||
return 0;
|
||||
|
||||
/* Copy data across, passing through filter BIOs for processing */
|
||||
SMIME_crlf_copy(data, sarg.ndef_bio, flags);
|
||||
|
||||
/* Finalize structure */
|
||||
if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
|
||||
return 0;
|
||||
|
||||
/* Now remove any digests prepended to the BIO */
|
||||
|
||||
while (sarg.ndef_bio != out)
|
||||
{
|
||||
tmpbio = BIO_pop(sarg.ndef_bio);
|
||||
BIO_free(sarg.ndef_bio);
|
||||
sarg.ndef_bio = tmpbio;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* SMIME reader: handle multipart/signed and opaque signing.
|
||||
* in multipart case the content is placed in a memory BIO
|
||||
* pointed to by "bcont". In opaque this is set to NULL
|
||||
*/
|
||||
|
||||
ASN1_VALUE *SMIME_read_asn1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIO *asnin;
|
||||
STACK_OF(MIME_HEADER) *headers = NULL;
|
||||
STACK_OF(BIO) *parts = NULL;
|
||||
MIME_HEADER *hdr;
|
||||
MIME_PARAM *prm;
|
||||
ASN1_VALUE *val;
|
||||
int ret;
|
||||
|
||||
if(bcont) *bcont = NULL;
|
||||
|
||||
if (!(headers = mime_parse_hdr(bio))) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_PARSE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle multipart/signed */
|
||||
|
||||
if(!strcmp(hdr->value, "multipart/signed")) {
|
||||
/* Split into two parts */
|
||||
prm = mime_param_find(hdr, "boundary");
|
||||
if(!prm || !prm->param_value) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
|
||||
return NULL;
|
||||
}
|
||||
ret = multi_split(bio, prm->param_value, &parts);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
if(!ret || (sk_BIO_num(parts) != 2) ) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parse the signature piece */
|
||||
asnin = sk_BIO_value(parts, 1);
|
||||
|
||||
if (!(headers = mime_parse_hdr(asnin))) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_SIG_PARSE_ERROR);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get content type */
|
||||
|
||||
if(!(hdr = mime_hdr_find(headers, "content-type")) ||
|
||||
!hdr->value) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(strcmp(hdr->value, "application/x-pkcs7-signature") &&
|
||||
strcmp(hdr->value, "application/pkcs7-signature")) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
/* Read in ASN1 */
|
||||
if(!(val = b64_read_asn1(asnin, it))) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_ASN1_SIG_PARSE_ERROR);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(bcont) {
|
||||
*bcont = sk_BIO_value(parts, 0);
|
||||
BIO_free(asnin);
|
||||
sk_BIO_free(parts);
|
||||
} else sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* OK, if not multipart/signed try opaque signature */
|
||||
|
||||
if (strcmp (hdr->value, "application/x-pkcs7-mime") &&
|
||||
strcmp (hdr->value, "application/pkcs7-mime")) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
|
||||
if(!(val = b64_read_asn1(bio, it))) {
|
||||
ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
/* Copy text from one BIO to another making the output CRLF at EOL */
|
||||
int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
|
||||
{
|
||||
BIO *bf;
|
||||
char eol;
|
||||
int len;
|
||||
char linebuf[MAX_SMLEN];
|
||||
/* Buffer output so we don't write one line at a time. This is
|
||||
* useful when streaming as we don't end up with one OCTET STRING
|
||||
* per line.
|
||||
*/
|
||||
bf = BIO_new(BIO_f_buffer());
|
||||
if (!bf)
|
||||
return 0;
|
||||
out = BIO_push(bf, out);
|
||||
if(flags & SMIME_BINARY)
|
||||
{
|
||||
while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
|
||||
BIO_write(out, linebuf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(flags & SMIME_TEXT)
|
||||
BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
|
||||
while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0)
|
||||
{
|
||||
eol = strip_eol(linebuf, &len);
|
||||
if (len)
|
||||
BIO_write(out, linebuf, len);
|
||||
if(eol) BIO_write(out, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
(void)BIO_flush(out);
|
||||
BIO_pop(out);
|
||||
BIO_free(bf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Strip off headers if they are text/plain */
|
||||
int SMIME_text(BIO *in, BIO *out)
|
||||
{
|
||||
char iobuf[4096];
|
||||
int len;
|
||||
STACK_OF(MIME_HEADER) *headers;
|
||||
MIME_HEADER *hdr;
|
||||
|
||||
if (!(headers = mime_parse_hdr(in))) {
|
||||
ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_PARSE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
|
||||
ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_NO_CONTENT_TYPE);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp (hdr->value, "text/plain")) {
|
||||
ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return 0;
|
||||
}
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
|
||||
BIO_write(out, iobuf, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Split a multipart/XXX message body into component parts: result is
|
||||
* canonical parts in a STACK of bios
|
||||
*/
|
||||
|
||||
static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
|
||||
{
|
||||
char linebuf[MAX_SMLEN];
|
||||
int len, blen;
|
||||
int eol = 0, next_eol = 0;
|
||||
BIO *bpart = NULL;
|
||||
STACK_OF(BIO) *parts;
|
||||
char state, part, first;
|
||||
|
||||
blen = strlen(bound);
|
||||
part = 0;
|
||||
state = 0;
|
||||
first = 1;
|
||||
parts = sk_BIO_new_null();
|
||||
*ret = parts;
|
||||
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
|
||||
state = mime_bound_check(linebuf, len, bound, blen);
|
||||
if(state == 1) {
|
||||
first = 1;
|
||||
part++;
|
||||
} else if(state == 2) {
|
||||
sk_BIO_push(parts, bpart);
|
||||
return 1;
|
||||
} else if(part) {
|
||||
/* Strip CR+LF from linebuf */
|
||||
next_eol = strip_eol(linebuf, &len);
|
||||
if(first) {
|
||||
first = 0;
|
||||
if(bpart) sk_BIO_push(parts, bpart);
|
||||
bpart = BIO_new(BIO_s_mem());
|
||||
BIO_set_mem_eof_return(bpart, 0);
|
||||
} else if (eol)
|
||||
BIO_write(bpart, "\r\n", 2);
|
||||
eol = next_eol;
|
||||
if (len)
|
||||
BIO_write(bpart, linebuf, len);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the big one: parse MIME header lines up to message body */
|
||||
|
||||
#define MIME_INVALID 0
|
||||
#define MIME_START 1
|
||||
#define MIME_TYPE 2
|
||||
#define MIME_NAME 3
|
||||
#define MIME_VALUE 4
|
||||
#define MIME_QUOTE 5
|
||||
#define MIME_COMMENT 6
|
||||
|
||||
|
||||
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
|
||||
{
|
||||
char *p, *q, c;
|
||||
char *ntmp;
|
||||
char linebuf[MAX_SMLEN];
|
||||
MIME_HEADER *mhdr = NULL;
|
||||
STACK_OF(MIME_HEADER) *headers;
|
||||
int len, state, save_state = 0;
|
||||
|
||||
headers = sk_MIME_HEADER_new(mime_hdr_cmp);
|
||||
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
|
||||
/* If whitespace at line start then continuation line */
|
||||
if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME;
|
||||
else state = MIME_START;
|
||||
ntmp = NULL;
|
||||
/* Go through all characters */
|
||||
for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
|
||||
|
||||
/* State machine to handle MIME headers
|
||||
* if this looks horrible that's because it *is*
|
||||
*/
|
||||
|
||||
switch(state) {
|
||||
case MIME_START:
|
||||
if(c == ':') {
|
||||
state = MIME_TYPE;
|
||||
*p = 0;
|
||||
ntmp = strip_ends(q);
|
||||
q = p + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_TYPE:
|
||||
if(c == ';') {
|
||||
mime_debug("Found End Value\n");
|
||||
*p = 0;
|
||||
mhdr = mime_hdr_new(ntmp, strip_ends(q));
|
||||
sk_MIME_HEADER_push(headers, mhdr);
|
||||
ntmp = NULL;
|
||||
q = p + 1;
|
||||
state = MIME_NAME;
|
||||
} else if(c == '(') {
|
||||
save_state = state;
|
||||
state = MIME_COMMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_COMMENT:
|
||||
if(c == ')') {
|
||||
state = save_state;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_NAME:
|
||||
if(c == '=') {
|
||||
state = MIME_VALUE;
|
||||
*p = 0;
|
||||
ntmp = strip_ends(q);
|
||||
q = p + 1;
|
||||
}
|
||||
break ;
|
||||
|
||||
case MIME_VALUE:
|
||||
if(c == ';') {
|
||||
state = MIME_NAME;
|
||||
*p = 0;
|
||||
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
|
||||
ntmp = NULL;
|
||||
q = p + 1;
|
||||
} else if (c == '"') {
|
||||
mime_debug("Found Quote\n");
|
||||
state = MIME_QUOTE;
|
||||
} else if(c == '(') {
|
||||
save_state = state;
|
||||
state = MIME_COMMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_QUOTE:
|
||||
if(c == '"') {
|
||||
mime_debug("Found Match Quote\n");
|
||||
state = MIME_VALUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(state == MIME_TYPE) {
|
||||
mhdr = mime_hdr_new(ntmp, strip_ends(q));
|
||||
sk_MIME_HEADER_push(headers, mhdr);
|
||||
} else if(state == MIME_VALUE)
|
||||
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
|
||||
if(p == linebuf) break; /* Blank line means end of headers */
|
||||
}
|
||||
|
||||
return headers;
|
||||
|
||||
}
|
||||
|
||||
static char *strip_ends(char *name)
|
||||
{
|
||||
return strip_end(strip_start(name));
|
||||
}
|
||||
|
||||
/* Strip a parameter of whitespace from start of param */
|
||||
static char *strip_start(char *name)
|
||||
{
|
||||
char *p, c;
|
||||
/* Look for first non white space or quote */
|
||||
for(p = name; (c = *p) ;p++) {
|
||||
if(c == '"') {
|
||||
/* Next char is start of string if non null */
|
||||
if(p[1]) return p + 1;
|
||||
/* Else null string */
|
||||
return NULL;
|
||||
}
|
||||
if(!isspace((unsigned char)c)) return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* As above but strip from end of string : maybe should handle brackets? */
|
||||
static char *strip_end(char *name)
|
||||
{
|
||||
char *p, c;
|
||||
if(!name) return NULL;
|
||||
/* Look for first non white space or quote */
|
||||
for(p = name + strlen(name) - 1; p >= name ;p--) {
|
||||
c = *p;
|
||||
if(c == '"') {
|
||||
if(p - 1 == name) return NULL;
|
||||
*p = 0;
|
||||
return name;
|
||||
}
|
||||
if(isspace((unsigned char)c)) *p = 0;
|
||||
else return name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MIME_HEADER *mime_hdr_new(char *name, char *value)
|
||||
{
|
||||
MIME_HEADER *mhdr;
|
||||
char *tmpname, *tmpval, *p;
|
||||
int c;
|
||||
if(name) {
|
||||
if(!(tmpname = BUF_strdup(name))) return NULL;
|
||||
for(p = tmpname ; *p; p++) {
|
||||
c = *p;
|
||||
if(isupper(c)) {
|
||||
c = tolower(c);
|
||||
*p = c;
|
||||
}
|
||||
}
|
||||
} else tmpname = NULL;
|
||||
if(value) {
|
||||
if(!(tmpval = BUF_strdup(value))) return NULL;
|
||||
for(p = tmpval ; *p; p++) {
|
||||
c = *p;
|
||||
if(isupper(c)) {
|
||||
c = tolower(c);
|
||||
*p = c;
|
||||
}
|
||||
}
|
||||
} else tmpval = NULL;
|
||||
mhdr = (MIME_HEADER *) OPENSSL_malloc(sizeof(MIME_HEADER));
|
||||
if(!mhdr) return NULL;
|
||||
mhdr->name = tmpname;
|
||||
mhdr->value = tmpval;
|
||||
if(!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) return NULL;
|
||||
return mhdr;
|
||||
}
|
||||
|
||||
static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
|
||||
{
|
||||
char *tmpname, *tmpval, *p;
|
||||
int c;
|
||||
MIME_PARAM *mparam;
|
||||
if(name) {
|
||||
tmpname = BUF_strdup(name);
|
||||
if(!tmpname) return 0;
|
||||
for(p = tmpname ; *p; p++) {
|
||||
c = *p;
|
||||
if(isupper(c)) {
|
||||
c = tolower(c);
|
||||
*p = c;
|
||||
}
|
||||
}
|
||||
} else tmpname = NULL;
|
||||
if(value) {
|
||||
tmpval = BUF_strdup(value);
|
||||
if(!tmpval) return 0;
|
||||
} else tmpval = NULL;
|
||||
/* Parameter values are case sensitive so leave as is */
|
||||
mparam = (MIME_PARAM *) OPENSSL_malloc(sizeof(MIME_PARAM));
|
||||
if(!mparam) return 0;
|
||||
mparam->param_name = tmpname;
|
||||
mparam->param_value = tmpval;
|
||||
sk_MIME_PARAM_push(mhdr->params, mparam);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mime_hdr_cmp(const MIME_HEADER * const *a,
|
||||
const MIME_HEADER * const *b)
|
||||
{
|
||||
return(strcmp((*a)->name, (*b)->name));
|
||||
}
|
||||
|
||||
static int mime_param_cmp(const MIME_PARAM * const *a,
|
||||
const MIME_PARAM * const *b)
|
||||
{
|
||||
return(strcmp((*a)->param_name, (*b)->param_name));
|
||||
}
|
||||
|
||||
/* Find a header with a given name (if possible) */
|
||||
|
||||
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name)
|
||||
{
|
||||
MIME_HEADER htmp;
|
||||
int idx;
|
||||
htmp.name = name;
|
||||
idx = sk_MIME_HEADER_find(hdrs, &htmp);
|
||||
if(idx < 0) return NULL;
|
||||
return sk_MIME_HEADER_value(hdrs, idx);
|
||||
}
|
||||
|
||||
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name)
|
||||
{
|
||||
MIME_PARAM param;
|
||||
int idx;
|
||||
param.param_name = name;
|
||||
idx = sk_MIME_PARAM_find(hdr->params, ¶m);
|
||||
if(idx < 0) return NULL;
|
||||
return sk_MIME_PARAM_value(hdr->params, idx);
|
||||
}
|
||||
|
||||
static void mime_hdr_free(MIME_HEADER *hdr)
|
||||
{
|
||||
if(hdr->name) OPENSSL_free(hdr->name);
|
||||
if(hdr->value) OPENSSL_free(hdr->value);
|
||||
if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
|
||||
OPENSSL_free(hdr);
|
||||
}
|
||||
|
||||
static void mime_param_free(MIME_PARAM *param)
|
||||
{
|
||||
if(param->param_name) OPENSSL_free(param->param_name);
|
||||
if(param->param_value) OPENSSL_free(param->param_value);
|
||||
OPENSSL_free(param);
|
||||
}
|
||||
|
||||
/* Check for a multipart boundary. Returns:
|
||||
* 0 : no boundary
|
||||
* 1 : part boundary
|
||||
* 2 : final boundary
|
||||
*/
|
||||
static int mime_bound_check(char *line, int linelen, char *bound, int blen)
|
||||
{
|
||||
if(linelen == -1) linelen = strlen(line);
|
||||
if(blen == -1) blen = strlen(bound);
|
||||
/* Quickly eliminate if line length too short */
|
||||
if(blen + 2 > linelen) return 0;
|
||||
/* Check for part boundary */
|
||||
if(!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) {
|
||||
if(!strncmp(line + blen + 2, "--", 2)) return 2;
|
||||
else return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int strip_eol(char *linebuf, int *plen)
|
||||
{
|
||||
int len = *plen;
|
||||
char *p, c;
|
||||
int is_eol = 0;
|
||||
p = linebuf + len - 1;
|
||||
for (p = linebuf + len - 1; len > 0; len--, p--)
|
||||
{
|
||||
c = *p;
|
||||
if (c == '\n')
|
||||
is_eol = 1;
|
||||
else if (c != '\r')
|
||||
break;
|
||||
}
|
||||
*plen = len;
|
||||
return is_eol;
|
||||
}
|
246
crypto/asn1/bio_ndef.c
Normal file
246
crypto/asn1/bio_ndef.c
Normal file
@ -0,0 +1,246 @@
|
||||
/* bio_ndef.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/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifndef OPENSSL_SYSNAME_NETWARE
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
/* Experimental NDEF ASN1 BIO support routines */
|
||||
|
||||
/* The usage is quite simple, initialize an ASN1 structure,
|
||||
* get a BIO from it then any data written through the BIO
|
||||
* will end up translated to approptiate format on the fly.
|
||||
* The data is streamed out and does *not* need to be
|
||||
* all held in memory at once.
|
||||
*
|
||||
* When the BIO is flushed the output is finalized and any
|
||||
* signatures etc written out.
|
||||
*
|
||||
* The BIO is a 'proper' BIO and can handle non blocking I/O
|
||||
* correctly.
|
||||
*
|
||||
* The usage is simple. The implementation is *not*...
|
||||
*/
|
||||
|
||||
/* BIO support data stored in the ASN1 BIO ex_arg */
|
||||
|
||||
typedef struct ndef_aux_st
|
||||
{
|
||||
/* ASN1 structure this BIO refers to */
|
||||
ASN1_VALUE *val;
|
||||
const ASN1_ITEM *it;
|
||||
/* Top of the BIO chain */
|
||||
BIO *ndef_bio;
|
||||
/* Output BIO */
|
||||
BIO *out;
|
||||
/* Boundary where content is inserted */
|
||||
unsigned char **boundary;
|
||||
/* DER buffer start */
|
||||
unsigned char *derbuf;
|
||||
} NDEF_SUPPORT;
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
|
||||
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux = NULL;
|
||||
BIO *asn_bio = NULL;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!aux && !aux->asn1_cb)
|
||||
{
|
||||
ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
|
||||
asn_bio = BIO_new(BIO_f_asn1());
|
||||
|
||||
/* ASN1 bio needs to be next to output BIO */
|
||||
|
||||
out = BIO_push(asn_bio, out);
|
||||
|
||||
if (!ndef_aux || !asn_bio || !out)
|
||||
goto err;
|
||||
|
||||
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
|
||||
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
|
||||
|
||||
/* Now let callback prepend any digest, cipher etc BIOs
|
||||
* ASN1 structure needs.
|
||||
*/
|
||||
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
|
||||
goto err;
|
||||
|
||||
ndef_aux->val = val;
|
||||
ndef_aux->it = it;
|
||||
ndef_aux->ndef_bio = sarg.ndef_bio;
|
||||
ndef_aux->boundary = sarg.boundary;
|
||||
ndef_aux->out = out;
|
||||
|
||||
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
|
||||
|
||||
return sarg.ndef_bio;
|
||||
|
||||
err:
|
||||
if (asn_bio)
|
||||
BIO_free(asn_bio);
|
||||
if (ndef_aux)
|
||||
OPENSSL_free(ndef_aux);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
|
||||
*plen = *ndef_aux->boundary - *pbuf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
if (ndef_aux->derbuf)
|
||||
OPENSSL_free(ndef_aux->derbuf);
|
||||
|
||||
ndef_aux->derbuf = NULL;
|
||||
*pbuf = NULL;
|
||||
*plen = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
|
||||
if (!ndef_prefix_free(b, pbuf, plen, parg))
|
||||
return 0;
|
||||
OPENSSL_free(*pndef_aux);
|
||||
*pndef_aux = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
const ASN1_AUX *aux;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
aux = ndef_aux->it->funcs;
|
||||
|
||||
/* Finalize structures */
|
||||
sarg.ndef_bio = ndef_aux->ndef_bio;
|
||||
sarg.out = ndef_aux->out;
|
||||
sarg.boundary = ndef_aux->boundary;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
|
||||
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
|
||||
return 0;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
*pbuf = *ndef_aux->boundary;
|
||||
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
|
||||
|
||||
return 1;
|
||||
}
|
@ -71,61 +71,78 @@ ASN1_SEQUENCE(PBEPARAM) = {
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
|
||||
|
||||
/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
|
||||
|
||||
X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt,
|
||||
int saltlen)
|
||||
{
|
||||
/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
|
||||
|
||||
int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
|
||||
const unsigned char *salt, int saltlen)
|
||||
{
|
||||
PBEPARAM *pbe=NULL;
|
||||
ASN1_OBJECT *al;
|
||||
X509_ALGOR *algor;
|
||||
ASN1_TYPE *astype=NULL;
|
||||
ASN1_STRING *pbe_str=NULL;
|
||||
unsigned char *sstr;
|
||||
|
||||
if (!(pbe = PBEPARAM_new ())) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
|
||||
pbe = PBEPARAM_new();
|
||||
if (!pbe)
|
||||
{
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if(iter <= 0) iter = PKCS5_DEFAULT_ITER;
|
||||
if (!ASN1_INTEGER_set(pbe->iter, iter)) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
|
||||
}
|
||||
if(iter <= 0)
|
||||
iter = PKCS5_DEFAULT_ITER;
|
||||
if (!ASN1_INTEGER_set(pbe->iter, iter))
|
||||
{
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!saltlen) saltlen = PKCS5_SALT_LEN;
|
||||
if (!(pbe->salt->data = OPENSSL_malloc (saltlen))) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
|
||||
}
|
||||
if (!saltlen)
|
||||
saltlen = PKCS5_SALT_LEN;
|
||||
if (!ASN1_STRING_set(pbe->salt, NULL, saltlen))
|
||||
{
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
pbe->salt->length = saltlen;
|
||||
if (salt) memcpy (pbe->salt->data, salt, saltlen);
|
||||
else if (RAND_pseudo_bytes (pbe->salt->data, saltlen) < 0)
|
||||
}
|
||||
sstr = ASN1_STRING_data(pbe->salt);
|
||||
if (salt)
|
||||
memcpy(sstr, salt, saltlen);
|
||||
else if (RAND_pseudo_bytes(sstr, saltlen) < 0)
|
||||
goto err;
|
||||
|
||||
if (!(astype = ASN1_TYPE_new())) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
|
||||
if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str))
|
||||
{
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
astype->type = V_ASN1_SEQUENCE;
|
||||
if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM),
|
||||
&astype->value.sequence)) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
PBEPARAM_free (pbe);
|
||||
PBEPARAM_free(pbe);
|
||||
pbe = NULL;
|
||||
|
||||
al = OBJ_nid2obj(alg); /* never need to free al */
|
||||
if (!(algor = X509_ALGOR_new())) {
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ASN1_OBJECT_free(algor->algorithm);
|
||||
algor->algorithm = al;
|
||||
algor->parameter = astype;
|
||||
if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
|
||||
return 1;
|
||||
|
||||
return (algor);
|
||||
err:
|
||||
if (pbe != NULL) PBEPARAM_free(pbe);
|
||||
if (astype != NULL) ASN1_TYPE_free(astype);
|
||||
if (pbe != NULL)
|
||||
PBEPARAM_free(pbe);
|
||||
if (pbe_str != NULL)
|
||||
ASN1_STRING_free(pbe_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
|
||||
|
||||
X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
|
||||
const unsigned char *salt, int saltlen)
|
||||
{
|
||||
X509_ALGOR *ret;
|
||||
ret = X509_ALGOR_new();
|
||||
if (!ret)
|
||||
{
|
||||
ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
|
||||
return ret;
|
||||
|
||||
X509_ALGOR_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,12 @@ ASN1_SEQUENCE(X509_ALGOR) = {
|
||||
ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
|
||||
} ASN1_SEQUENCE_END(X509_ALGOR)
|
||||
|
||||
ASN1_ITEM_TEMPLATE(X509_ALGORS) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
|
||||
ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
|
||||
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
|
||||
|
||||
IMPLEMENT_STACK_OF(X509_ALGOR)
|
||||
|
@ -96,6 +96,7 @@ extern "C" {
|
||||
#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */
|
||||
#define BIO_TYPE_DGRAM (21|0x0400|0x0100)
|
||||
#define BIO_TYPE_ASN1 (22|0x0200) /* filter */
|
||||
#define BIO_TYPE_COMP (23|0x0200) /* filter */
|
||||
|
||||
#define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */
|
||||
#define BIO_TYPE_FILTER 0x0200
|
||||
|
132
crypto/cms/Makefile
Normal file
132
crypto/cms/Makefile
Normal file
@ -0,0 +1,132 @@
|
||||
#
|
||||
# OpenSSL/crypto/cms/Makefile
|
||||
#
|
||||
|
||||
DIR= cms
|
||||
TOP= ../..
|
||||
CC= cc
|
||||
INCLUDES= -I.. -I$(TOP) -I../../include
|
||||
CFLAG=-g
|
||||
MAKEFILE= Makefile
|
||||
AR= ar r
|
||||
|
||||
CFLAGS= $(INCLUDES) $(CFLAG)
|
||||
|
||||
GENERAL=Makefile
|
||||
TEST=
|
||||
APPS=
|
||||
|
||||
LIB=$(TOP)/libcrypto.a
|
||||
LIBSRC= cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
|
||||
cms_sd.c cms_dd.c cms_cd.c cms_env.c
|
||||
LIBOBJ= cms_lib.o cms_asn1.o cms_att.o cms_io.o cms_smime.o cms_err.o \
|
||||
cms_sd.o cms_dd.o cms_cd.o cms_env.o
|
||||
|
||||
SRC= $(LIBSRC)
|
||||
|
||||
EXHEADER= cms.h
|
||||
HEADER= cms_lcl.h $(EXHEADER)
|
||||
|
||||
ALL= $(GENERAL) $(SRC) $(HEADER)
|
||||
|
||||
top:
|
||||
(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
|
||||
|
||||
test:
|
||||
|
||||
all: lib
|
||||
|
||||
lib: $(LIBOBJ)
|
||||
$(AR) $(LIB) $(LIBOBJ)
|
||||
$(RANLIB) $(LIB) || echo Never mind.
|
||||
@touch lib
|
||||
|
||||
files:
|
||||
$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
|
||||
|
||||
links:
|
||||
@$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
|
||||
@$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
|
||||
@$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
|
||||
|
||||
install:
|
||||
@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
|
||||
@headerlist="$(EXHEADER)"; for i in $$headerlist ; \
|
||||
do \
|
||||
(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
|
||||
chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
|
||||
done;
|
||||
|
||||
tags:
|
||||
ctags $(SRC)
|
||||
|
||||
tests:
|
||||
|
||||
lint:
|
||||
lint -DLINT $(INCLUDES) $(SRC)>fluff
|
||||
|
||||
depend:
|
||||
@[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
|
||||
$(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC)
|
||||
|
||||
dclean:
|
||||
$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
|
||||
mv -f Makefile.new $(MAKEFILE)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
cms_asn1.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
|
||||
cms_asn1.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
|
||||
cms_asn1.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
|
||||
cms_asn1.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
|
||||
cms_asn1.o: ../../include/openssl/ecdsa.h ../../include/openssl/evp.h
|
||||
cms_asn1.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
cms_asn1.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
|
||||
cms_asn1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
cms_asn1.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
|
||||
cms_asn1.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
cms_asn1.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
|
||||
cms_asn1.o: ../../include/openssl/x509_vfy.h cms.h cms_asn1.c cms_lcl.h
|
||||
cms_att.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
|
||||
cms_att.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
|
||||
cms_att.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
|
||||
cms_att.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
|
||||
cms_att.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
|
||||
cms_att.o: ../../include/openssl/err.h ../../include/openssl/evp.h
|
||||
cms_att.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
cms_att.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
|
||||
cms_att.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
cms_att.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
|
||||
cms_att.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
cms_att.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
|
||||
cms_att.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h
|
||||
cms_att.o: cms.h cms_att.c cms_lcl.h
|
||||
cms_lib.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
|
||||
cms_lib.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
|
||||
cms_lib.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
|
||||
cms_lib.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
|
||||
cms_lib.o: ../../include/openssl/ecdsa.h ../../include/openssl/evp.h
|
||||
cms_lib.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
cms_lib.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
|
||||
cms_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
cms_lib.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
|
||||
cms_lib.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
cms_lib.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
|
||||
cms_lib.o: ../../include/openssl/x509_vfy.h cms.h cms_lcl.h cms_lib.c
|
||||
cms_sd.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
|
||||
cms_sd.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
|
||||
cms_sd.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
|
||||
cms_sd.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
|
||||
cms_sd.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
|
||||
cms_sd.o: ../../include/openssl/err.h ../../include/openssl/evp.h
|
||||
cms_sd.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
cms_sd.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
|
||||
cms_sd.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
cms_sd.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
|
||||
cms_sd.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
cms_sd.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
|
||||
cms_sd.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h cms.h
|
||||
cms_sd.o: cms_lcl.h cms_sd.c
|
324
crypto/cms/cms.h
Normal file
324
crypto/cms/cms.h
Normal file
@ -0,0 +1,324 @@
|
||||
/* 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 <openssl/x509.h>
|
||||
|
||||
#ifdef OPENSSL_NO_CMS
|
||||
#error CMS is disabled.
|
||||
#endif
|
||||
|
||||
#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;
|
||||
|
||||
DECLARE_STACK_OF(CMS_SignerInfo)
|
||||
DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
|
||||
DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
|
||||
|
||||
#define CMS_SIGNERINFO_ISSUER_SERIAL 0
|
||||
#define CMS_SIGNERINFO_KEYIDENTIFIER 1
|
||||
|
||||
/* 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
|
||||
|
||||
const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
|
||||
CMS_ContentInfo *CMS_Data_Create(void);
|
||||
|
||||
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, int flags);
|
||||
|
||||
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
|
||||
BIO *data, 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_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
||||
X509_STORE *store, BIO *dcont, BIO *out, 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 *data,
|
||||
unsigned int flags);
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
/* 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_CMS_ADD1_RECIPIENT_CERT 99
|
||||
#define CMS_F_CMS_ADD1_SIGNER 100
|
||||
#define CMS_F_CMS_ADD1_SIGNINGTIME 101
|
||||
#define CMS_F_CMS_COMPRESS 102
|
||||
#define CMS_F_CMS_COMPRESSEDDATA_CREATE 103
|
||||
#define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 104
|
||||
#define CMS_F_CMS_COPY_CONTENT 105
|
||||
#define CMS_F_CMS_COPY_MESSAGEDIGEST 106
|
||||
#define CMS_F_CMS_DATA 107
|
||||
#define CMS_F_CMS_DATAFINAL 108
|
||||
#define CMS_F_CMS_DATAINIT 109
|
||||
#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 110
|
||||
#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 111
|
||||
#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 112
|
||||
#define CMS_F_CMS_DIGEST_VERIFY 113
|
||||
#define CMS_F_CMS_ENVELOPED_DATA_INIT 114
|
||||
#define CMS_F_CMS_FINAL 115
|
||||
#define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 116
|
||||
#define CMS_F_CMS_GET0_CONTENT 117
|
||||
#define CMS_F_CMS_GET0_ECONTENT_TYPE 118
|
||||
#define CMS_F_CMS_GET0_ENVELOPED 119
|
||||
#define CMS_F_CMS_GET0_REVOCATION_CHOICES 120
|
||||
#define CMS_F_CMS_GET0_SIGNED 121
|
||||
#define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 122
|
||||
#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 123
|
||||
#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 124
|
||||
#define CMS_F_CMS_SET1_SIGNERIDENTIFIER 125
|
||||
#define CMS_F_CMS_SET_DETACHED 126
|
||||
#define CMS_F_CMS_SIGN 127
|
||||
#define CMS_F_CMS_SIGNED_DATA_INIT 128
|
||||
#define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 129
|
||||
#define CMS_F_CMS_SIGNERINFO_SIGN 130
|
||||
#define CMS_F_CMS_SIGNERINFO_VERIFY 131
|
||||
#define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 132
|
||||
#define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 133
|
||||
#define CMS_F_CMS_STREAM 134
|
||||
#define CMS_F_CMS_UNCOMPRESS 135
|
||||
#define CMS_F_CMS_VERIFY 136
|
||||
|
||||
/* Reason codes. */
|
||||
#define CMS_R_ADD_SIGNER_ERROR 99
|
||||
#define CMS_R_CERTIFICATE_VERIFY_ERROR 100
|
||||
#define CMS_R_CMS_DATAFINAL_ERROR 101
|
||||
#define CMS_R_CONTENT_NOT_FOUND 102
|
||||
#define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 103
|
||||
#define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 104
|
||||
#define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 105
|
||||
#define CMS_R_CONTENT_VERIFY_ERROR 106
|
||||
#define CMS_R_CTRL_ERROR 107
|
||||
#define CMS_R_CTRL_FAILURE 108
|
||||
#define CMS_R_ERROR_GETTING_PUBLIC_KEY 109
|
||||
#define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 110
|
||||
#define CMS_R_MD_BIO_INIT_ERROR 111
|
||||
#define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 112
|
||||
#define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 113
|
||||
#define CMS_R_NOT_KEY_TRANSPORT 114
|
||||
#define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 115
|
||||
#define CMS_R_NO_CONTENT 116
|
||||
#define CMS_R_NO_DEFAULT_DIGEST 117
|
||||
#define CMS_R_NO_DIGEST_SET 118
|
||||
#define CMS_R_NO_MATCHING_DIGEST 119
|
||||
#define CMS_R_NO_PRIVATE_KEY 120
|
||||
#define CMS_R_NO_PUBLIC_KEY 121
|
||||
#define CMS_R_NO_SIGNERS 122
|
||||
#define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 123
|
||||
#define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 124
|
||||
#define CMS_R_SIGNFINAL_ERROR 125
|
||||
#define CMS_R_SMIME_TEXT_ERROR 126
|
||||
#define CMS_R_STORE_INIT_ERROR 127
|
||||
#define CMS_R_TYPE_NOT_COMPRESSED_DATA 128
|
||||
#define CMS_R_TYPE_NOT_DATA 129
|
||||
#define CMS_R_TYPE_NOT_DIGESTED_DATA 130
|
||||
#define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 131
|
||||
#define CMS_R_UNKNOWN_DIGEST_ALGORIHM 132
|
||||
#define CMS_R_UNKNOWN_ID 133
|
||||
#define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 134
|
||||
#define CMS_R_UNSUPPORTED_CONTENT_TYPE 135
|
||||
#define CMS_R_UNSUPPORTED_TYPE 136
|
||||
#define CMS_R_VERIFICATION_FAILURE 137
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
328
crypto/cms/cms_asn1.c
Normal file
328
crypto/cms/cms_asn1.c
Normal file
@ -0,0 +1,328 @@
|
||||
/* 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 "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 EVP_PKEY */
|
||||
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);
|
||||
}
|
||||
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_SignedData, certificates, CMS_CertificateChoices, 0),
|
||||
ASN1_IMP_SET_OF_OPT(CMS_SignedData, 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)
|
||||
|
||||
ASN1_SEQUENCE(CMS_RecipientEncryptedKey) = {
|
||||
ASN1_SIMPLE(CMS_RecipientEncryptedKey, rid, CMS_KeyAgreeRecipientIdentifier),
|
||||
ASN1_SIMPLE(CMS_RecipientEncryptedKey, encryptedKey, ASN1_OCTET_STRING)
|
||||
} ASN1_SEQUENCE_END(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)
|
||||
|
||||
ASN1_SEQUENCE(CMS_KeyAgreeRecipientInfo) = {
|
||||
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(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)
|
||||
|
||||
ASN1_CHOICE(CMS_RecipientInfo) = {
|
||||
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(CMS_RecipientInfo)
|
||||
|
||||
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;
|
||||
if (pval)
|
||||
cms = (CMS_ContentInfo *)*pval;
|
||||
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)
|
||||
|
195
crypto/cms/cms_att.c
Normal file
195
crypto/cms/cms_att.c
Normal file
@ -0,0 +1,195 @@
|
||||
/* 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 */
|
135
crypto/cms/cms_cd.c
Normal file
135
crypto/cms/cms_cd.c
Normal file
@ -0,0 +1,135 @@
|
||||
/* 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 <openssl/cms.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/comp.h>
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.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
|
151
crypto/cms/cms_dd.c
Normal file
151
crypto/cms/cms_dd.c
Normal file
@ -0,0 +1,151 @@
|
||||
/* 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 <openssl/cms.h>
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.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;
|
||||
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_digest)
|
||||
return NULL;
|
||||
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 != 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;
|
||||
|
||||
}
|
253
crypto/cms/cms_env.c
Normal file
253
crypto/cms/cms_env.c
Normal file
@ -0,0 +1,253 @@
|
||||
/* 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 <openssl/cms.h>
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* CMS EnvelopedData Utilities */
|
||||
|
||||
DECLARE_ASN1_ITEM(CMS_EnvelopedData)
|
||||
DECLARE_ASN1_ITEM(CMS_RecipientInfo)
|
||||
DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
|
||||
|
||||
#if 0
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_EnvelopedData)
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_RecipientInfo)
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_KeyTransRecipientInfo)
|
||||
#endif
|
||||
|
||||
DECLARE_STACK_OF(CMS_RecipientInfo)
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
/* Add a recipient certificate. For now only handle key transport.
|
||||
* If we ever handle key agreement will need updating.
|
||||
*/
|
||||
|
||||
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
|
||||
X509 *recip, unsigned int flags)
|
||||
{
|
||||
CMS_RecipientInfo *ri = NULL;
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
CMS_EnvelopedData *env;
|
||||
EVP_PKEY *pk = NULL;
|
||||
int i, type;
|
||||
/* Init enveloped data */
|
||||
env = cms_enveloped_data_init(cms);
|
||||
if (!env)
|
||||
goto err;
|
||||
|
||||
/* Initialized recipient info */
|
||||
ri = M_ASN1_new_of(CMS_RecipientInfo);
|
||||
if (!ri)
|
||||
goto merr;
|
||||
|
||||
/* Initialize and add key transrport recipient info */
|
||||
|
||||
ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
|
||||
if (!ri->d.ktri)
|
||||
goto merr;
|
||||
ri->type = CMS_RECIPINFO_TRANS;
|
||||
|
||||
ktri = ri->d.ktri;
|
||||
|
||||
X509_check_purpose(recip, -1, -1);
|
||||
pk = X509_get_pubkey(recip);
|
||||
if (!pk)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
|
||||
CMS_R_ERROR_GETTING_PUBLIC_KEY);
|
||||
goto err;
|
||||
}
|
||||
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_USE_KEYID)
|
||||
{
|
||||
ktri->version = 2;
|
||||
type = CMS_RECIPINFO_KEYIDENTIFIER;
|
||||
}
|
||||
else
|
||||
{
|
||||
ktri->version = 0;
|
||||
type = CMS_RECIPINFO_ISSUER_SERIAL;
|
||||
}
|
||||
|
||||
/* Not a typo: RecipientIdentifier and SignerIdentifier are the
|
||||
* same structure.
|
||||
*/
|
||||
|
||||
if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))
|
||||
goto err;
|
||||
|
||||
if (pk->ameth && pk->ameth->pkey_ctrl)
|
||||
{
|
||||
i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE,
|
||||
0, ri);
|
||||
if (i == -2)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
|
||||
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (i <= 0)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
|
||||
CMS_R_CTRL_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
|
||||
goto merr;
|
||||
|
||||
return ri;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
if (ri)
|
||||
M_ASN1_free_of(ri, CMS_RecipientInfo);
|
||||
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;
|
||||
}
|
||||
|
||||
return cms_SignerIdentifier_get0_signer_id(ktri->rid,
|
||||
keyid, issuer, sno);
|
||||
}
|
||||
|
||||
int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
|
||||
{
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
if (ri->type != CMS_RECIPINFO_TRANS)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
|
||||
CMS_R_NOT_KEY_TRANSPORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cms_SignerIdentifier_cert_cmp(ktri->rid, cert);
|
||||
}
|
170
crypto/cms/cms_err.c
Normal file
170
crypto/cms/cms_err.c
Normal file
@ -0,0 +1,170 @@
|
||||
/* crypto/cms/cms_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2007 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 <openssl/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_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_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_ENVELOPED_DATA_INIT), "CMS_ENVELOPED_DATA_INIT"},
|
||||
{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_RECIPIENTINFO_KTRI_CERT_CMP), "CMS_RECIPIENTINFO_KTRI_CERT_CMP"},
|
||||
{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_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_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_VERIFY_ERROR),"certificate verify error"},
|
||||
{ERR_REASON(CMS_R_CMS_DATAFINAL_ERROR) ,"cms datafinal error"},
|
||||
{ERR_REASON(CMS_R_CONTENT_NOT_FOUND) ,"content not found"},
|
||||
{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_ERROR_GETTING_PUBLIC_KEY),"error getting public key"},
|
||||
{ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"},
|
||||
{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_NOT_KEY_TRANSPORT) ,"not key transport"},
|
||||
{ERR_REASON(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),"not supported for this key type"},
|
||||
{ERR_REASON(CMS_R_NO_CONTENT) ,"no content"},
|
||||
{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_MATCHING_DIGEST) ,"no matching digest"},
|
||||
{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_SIGNERS) ,"no signers"},
|
||||
{ERR_REASON(CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),"private key does not match certificate"},
|
||||
{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_UNABLE_TO_FINALIZE_CONTEXT),"unable to finalize context"},
|
||||
{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_TYPE) ,"unsupported type"},
|
||||
{ERR_REASON(CMS_R_VERIFICATION_FAILURE) ,"verification failure"},
|
||||
{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
|
||||
}
|
146
crypto/cms/cms_io.c
Normal file
146
crypto/cms/cms_io.c
Normal file
@ -0,0 +1,146 @@
|
||||
/* 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)
|
||||
|
||||
#if 0
|
||||
/* Streaming encode support for CMS */
|
||||
|
||||
static BIO *cmsbio_init(ASN1_VALUE *val, BIO *out)
|
||||
{
|
||||
return CMS_dataInit((CMS_ContentInfo *)val, out);
|
||||
}
|
||||
|
||||
static int cmsbio_final(ASN1_VALUE *val, BIO *cmsbio)
|
||||
{
|
||||
return CMS_dataFinal((CMS_ContentInfo *)val, cmsbio);
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
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, 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));
|
||||
}
|
||||
|
415
crypto/cms/cms_lcl.h
Normal file
415
crypto/cms/cms_lcl.h
Normal file
@ -0,0 +1,415 @@
|
||||
/* 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_OtherKeyAttribute_st CMS_OtherKeyAttribute;
|
||||
typedef struct CMS_RecipientKeyIdentifier_st CMS_RecipientKeyIdentifier;
|
||||
typedef struct CMS_KeyAgreeRecipientIdentifier_st CMS_KeyAgreeRecipientIdentifier;
|
||||
typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey;
|
||||
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_RecipientInfo_st CMS_RecipientInfo;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct CMS_RecipientInfo_st
|
||||
{
|
||||
int type;
|
||||
union {
|
||||
CMS_KeyTransRecipientInfo *ktri;
|
||||
CMS_KeyAgreeRecipientInfo *kari;
|
||||
CMS_KEKRecipientInfo *kekri;
|
||||
CMS_PasswordRecipientInfo *pwri;
|
||||
CMS_OtherRecipientInfo *ori;
|
||||
} d;
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct CMS_KeyAgreeRecipientInfo_st
|
||||
{
|
||||
long version;
|
||||
CMS_OriginatorIdentifierOrKey *originator;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
X509_ALGOR *keyEncryptionAlgorithm;
|
||||
STACK_OF(CMS_RecipientEncryptedKey) *recipientEncryptedKeys;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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_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
|
||||
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
607
crypto/cms/cms_lib.c
Normal file
607
crypto/cms/cms_lib.c
Normal file
@ -0,0 +1,607 @@
|
||||
/* 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/x509.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)
|
||||
|
||||
#if 0
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_CertificateChoices)
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_RevocationInfoChoice)
|
||||
#endif
|
||||
|
||||
|
||||
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
|
||||
|
||||
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_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)
|
||||
{
|
||||
EVP_MD_CTX_copy_ex(mctx, mtmp);
|
||||
return 1;
|
||||
}
|
||||
chain = BIO_next(chain);
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
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;
|
||||
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))
|
||||
return -1;
|
||||
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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:
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
967
crypto/cms/cms_sd.c
Normal file
967
crypto/cms/cms_sd.c
Normal file
@ -0,0 +1,967 @@
|
||||
/* 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/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/cms.h>
|
||||
#include "cms_lcl.h"
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/* 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);
|
||||
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
|
||||
sd->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:
|
||||
sid->d.issuerAndSerialNumber =
|
||||
M_ASN1_new_of(CMS_IssuerAndSerialNumber);
|
||||
if (!sid->d.issuerAndSerialNumber)
|
||||
goto merr;
|
||||
if (!X509_NAME_set(&sid->d.issuerAndSerialNumber->issuer,
|
||||
X509_get_issuer_name(cert)))
|
||||
goto merr;
|
||||
if (!ASN1_STRING_copy(
|
||||
sid->d.issuerAndSerialNumber->serialNumber,
|
||||
X509_get_serialNumber(cert)))
|
||||
goto merr;
|
||||
break;
|
||||
|
||||
case CMS_SIGNERINFO_KEYIDENTIFIER:
|
||||
sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid);
|
||||
if (!sid->d.subjectKeyIdentifier)
|
||||
goto merr;
|
||||
break;
|
||||
|
||||
default:
|
||||
CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sid->type = type;
|
||||
|
||||
return 1;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
|
||||
{
|
||||
ret = X509_NAME_cmp(sid->d.issuerAndSerialNumber->issuer,
|
||||
X509_get_issuer_name(cert));
|
||||
if (ret)
|
||||
return ret;
|
||||
return ASN1_INTEGER_cmp(sid->d.issuerAndSerialNumber->serialNumber,
|
||||
X509_get_serialNumber(cert));
|
||||
}
|
||||
else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
|
||||
{
|
||||
X509_check_purpose(cert, -1, -1);
|
||||
if (!cert->skid)
|
||||
return -1;
|
||||
return ASN1_OCTET_STRING_cmp(sid->d.subjectKeyIdentifier,
|
||||
cert->skid);
|
||||
}
|
||||
else
|
||||
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;
|
||||
|
||||
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 (pk->ameth && pk->ameth->pkey_ctrl)
|
||||
{
|
||||
i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN,
|
||||
0, si);
|
||||
if (i == -2)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_ADD1_SIGNER,
|
||||
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (i <= 0)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & CMS_NOATTR))
|
||||
{
|
||||
/* Copy content type across */
|
||||
ASN1_OBJECT *ctype =
|
||||
OBJ_dup(sd->encapContentInfo->eContentType);
|
||||
if (!ctype)
|
||||
goto merr;
|
||||
i = CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
|
||||
V_ASN1_OBJECT, ctype, -1);
|
||||
ASN1_OBJECT_free(ctype);
|
||||
if (i <= 0)
|
||||
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_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 (!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;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int cms_SignerInfo_content_sign(CMS_SignerInfo *si, BIO *chain)
|
||||
{
|
||||
EVP_MD_CTX mctx;
|
||||
int r = 0;
|
||||
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;
|
||||
|
||||
/* If any signed attributes calculate and add messageDigest attribute */
|
||||
|
||||
if (CMS_signed_get_attr_count(si) >= 0)
|
||||
{
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
unsigned int mdlen;
|
||||
EVP_DigestFinal_ex(&mctx, md, &mdlen);
|
||||
if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
|
||||
V_ASN1_OCTET_STRING,
|
||||
md, mdlen))
|
||||
goto err;
|
||||
if (!CMS_SignerInfo_sign(si))
|
||||
goto err;
|
||||
}
|
||||
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);
|
||||
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(si, chain))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CMS_SignerInfo_sign(CMS_SignerInfo *si)
|
||||
{
|
||||
EVP_MD_CTX 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;
|
||||
|
||||
EVP_MD_CTX_init(&mctx);
|
||||
|
||||
if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0)
|
||||
{
|
||||
if (!CMS_add1_signingTime(si, NULL))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
|
||||
goto err;
|
||||
|
||||
if (EVP_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 (EVP_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;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
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, &pctx, md, NULL, si->pkey) <= 0)
|
||||
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)
|
||||
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);
|
||||
cms_sd_set_version(sd);
|
||||
if (!sd)
|
||||
return NULL;
|
||||
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;
|
||||
int r = -1;
|
||||
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 messageDigest found compare it */
|
||||
|
||||
if (os)
|
||||
{
|
||||
unsigned char mval[EVP_MAX_MD_SIZE];
|
||||
unsigned int mlen;
|
||||
if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
|
||||
CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
|
||||
goto err;
|
||||
}
|
||||
if (mlen != 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
|
||||
{
|
||||
r = EVP_VerifyFinal(&mctx, si->signature->data,
|
||||
si->signature->length, si->pkey);
|
||||
if (r <= 0)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
|
||||
CMS_R_VERIFICATION_FAILURE);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
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;
|
||||
}
|
515
crypto/cms/cms_smime.c
Normal file
515
crypto/cms/cms_smime.c
Normal file
@ -0,0 +1,515 @@
|
||||
/* 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 <openssl/cms.h>
|
||||
#include "cms_lcl.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(flags & CMS_TEXT)
|
||||
{
|
||||
tmpout = BIO_new(BIO_s_mem());
|
||||
if(!tmpout)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
tmpout = out;
|
||||
|
||||
/* Read all content through chain to determine content digests */
|
||||
for (;;)
|
||||
{
|
||||
i=BIO_read(in,buf,sizeof(buf));
|
||||
if (i <= 0)
|
||||
break;
|
||||
if (tmpout)
|
||||
BIO_write(tmpout, buf, i);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
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, 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)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
||||
if (!pos || !*pos)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_NO_CONTENT);
|
||||
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);
|
||||
BIO_free_all(cont);
|
||||
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, 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_purpose(&ctx, X509_PURPOSE_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)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
||||
if (!pos || !*pos)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_CONTENT);
|
||||
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);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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))
|
||||
{
|
||||
CMSerr(CMS_F_CMS_VERIFY,
|
||||
CMS_R_CONTENT_VERIFY_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (dcont && (tmpin == dcont))
|
||||
BIO_pop(cmsbio);
|
||||
BIO_free_all(cmsbio);
|
||||
|
||||
if (cms_certs)
|
||||
sk_X509_pop_free(cms_certs, X509_free);
|
||||
if (crls)
|
||||
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
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 no signer or certs initialize signedData */
|
||||
if (!pkey && !i && !CMS_SignedData_init(cms))
|
||||
goto merr;
|
||||
|
||||
if(!(flags & CMS_DETACHED))
|
||||
CMS_set_detached(cms, 0);
|
||||
|
||||
if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, data, flags))
|
||||
return cms;
|
||||
|
||||
return cms;
|
||||
|
||||
merr:
|
||||
CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
err:
|
||||
if (cms)
|
||||
CMS_ContentInfo_free(cms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Placeholders for now... */
|
||||
|
||||
CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
|
||||
const EVP_CIPHER *cipher, unsigned int flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, BIO *data,
|
||||
unsigned int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMS_final(CMS_ContentInfo *cms, BIO *data, int flags)
|
||||
{
|
||||
BIO *cmsbio;
|
||||
int ret = 0;
|
||||
if (!(cmsbio = CMS_dataInit(cms, NULL)))
|
||||
{
|
||||
CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE);
|
||||
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:
|
||||
BIO_free_all(cmsbio);
|
||||
|
||||
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)
|
||||
{
|
||||
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
||||
if (!pos || !*pos)
|
||||
{
|
||||
CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_NO_CONTENT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
cont = CMS_dataInit(cms, dcont);
|
||||
if (!cont)
|
||||
return 0;
|
||||
r = cms_copy_content(out, cont, flags);
|
||||
BIO_free_all(cont);
|
||||
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, 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
|
@ -105,6 +105,7 @@ typedef int (*deflateEnd_ft)(z_streamp strm);
|
||||
typedef int (*deflate_ft)(z_streamp strm, int flush);
|
||||
typedef int (*deflateInit__ft)(z_streamp strm, int level,
|
||||
const char * version, int stream_size);
|
||||
typedef const char * (*zError__ft)(int err);
|
||||
static compress_ft p_compress=NULL;
|
||||
static inflateEnd_ft p_inflateEnd=NULL;
|
||||
static inflate_ft p_inflate=NULL;
|
||||
@ -112,6 +113,7 @@ static inflateInit__ft p_inflateInit_=NULL;
|
||||
static deflateEnd_ft p_deflateEnd=NULL;
|
||||
static deflate_ft p_deflate=NULL;
|
||||
static deflateInit__ft p_deflateInit_=NULL;
|
||||
static zError__ft p_zError=NULL;
|
||||
|
||||
static int zlib_loaded = 0; /* only attempt to init func pts once */
|
||||
static DSO *zlib_dso = NULL;
|
||||
@ -123,6 +125,7 @@ static DSO *zlib_dso = NULL;
|
||||
#define deflateEnd p_deflateEnd
|
||||
#define deflate p_deflate
|
||||
#define deflateInit_ p_deflateInit_
|
||||
#define zError p_zError
|
||||
#endif /* ZLIB_SHARED */
|
||||
|
||||
struct zlib_state
|
||||
@ -373,10 +376,13 @@ COMP_METHOD *COMP_zlib(void)
|
||||
p_deflateInit_
|
||||
= (deflateInit__ft) DSO_bind_func(zlib_dso,
|
||||
"deflateInit_");
|
||||
p_zError
|
||||
= (zError__ft) DSO_bind_func(zlib_dso,
|
||||
"zError");
|
||||
|
||||
if (p_compress && p_inflateEnd && p_inflate
|
||||
&& p_inflateInit_ && p_deflateEnd
|
||||
&& p_deflate && p_deflateInit_)
|
||||
&& p_deflate && p_deflateInit_ && p_zError)
|
||||
zlib_loaded++;
|
||||
}
|
||||
}
|
||||
@ -410,3 +416,386 @@ err:
|
||||
return(meth);
|
||||
}
|
||||
|
||||
void COMP_zlib_cleanup(void)
|
||||
{
|
||||
#ifdef ZLIB_SHARED
|
||||
if (zlib_dso)
|
||||
DSO_free(zlib_dso);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ZLIB
|
||||
|
||||
/* Zlib based compression/decompression filter BIO */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *ibuf; /* Input buffer */
|
||||
int ibufsize; /* Buffer size */
|
||||
z_stream zin; /* Input decompress context */
|
||||
unsigned char *obuf; /* Output buffer */
|
||||
int obufsize; /* Output buffer size */
|
||||
unsigned char *optr; /* Position in output buffer */
|
||||
int ocount; /* Amount of data in output buffer */
|
||||
int odone; /* deflate EOF */
|
||||
int comp_level; /* Compression level to use */
|
||||
z_stream zout; /* Output compression context */
|
||||
} BIO_ZLIB_CTX;
|
||||
|
||||
#define ZLIB_DEFAULT_BUFSIZE 1024
|
||||
|
||||
static int bio_zlib_new(BIO *bi);
|
||||
static int bio_zlib_free(BIO *bi);
|
||||
static int bio_zlib_read(BIO *b, char *out, int outl);
|
||||
static int bio_zlib_write(BIO *b, const char *in, int inl);
|
||||
static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr);
|
||||
static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp);
|
||||
|
||||
static BIO_METHOD bio_meth_zlib =
|
||||
{
|
||||
BIO_TYPE_COMP,
|
||||
"zlib",
|
||||
bio_zlib_write,
|
||||
bio_zlib_read,
|
||||
NULL,
|
||||
NULL,
|
||||
bio_zlib_ctrl,
|
||||
bio_zlib_new,
|
||||
bio_zlib_free,
|
||||
bio_zlib_callback_ctrl
|
||||
};
|
||||
|
||||
BIO_METHOD *BIO_f_zlib(void)
|
||||
{
|
||||
return &bio_meth_zlib;
|
||||
}
|
||||
|
||||
|
||||
static int bio_zlib_new(BIO *bi)
|
||||
{
|
||||
BIO_ZLIB_CTX *ctx;
|
||||
#ifdef ZLIB_SHARED
|
||||
(void)COMP_zlib();
|
||||
if (!zlib_loaded)
|
||||
{
|
||||
COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX));
|
||||
if(!ctx)
|
||||
{
|
||||
COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
ctx->ibuf = NULL;
|
||||
ctx->obuf = NULL;
|
||||
ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE;
|
||||
ctx->obufsize = ZLIB_DEFAULT_BUFSIZE;
|
||||
ctx->zin.zalloc = Z_NULL;
|
||||
ctx->zin.zfree = Z_NULL;
|
||||
ctx->zin.next_in = NULL;
|
||||
ctx->zin.avail_in = 0;
|
||||
ctx->zin.next_out = NULL;
|
||||
ctx->zin.avail_out = 0;
|
||||
ctx->zout.zalloc = Z_NULL;
|
||||
ctx->zout.zfree = Z_NULL;
|
||||
ctx->zout.next_in = NULL;
|
||||
ctx->zout.avail_in = 0;
|
||||
ctx->zout.next_out = NULL;
|
||||
ctx->zout.avail_out = 0;
|
||||
ctx->odone = 0;
|
||||
ctx->comp_level = Z_DEFAULT_COMPRESSION;
|
||||
bi->init = 1;
|
||||
bi->ptr = (char *)ctx;
|
||||
bi->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_zlib_free(BIO *bi)
|
||||
{
|
||||
BIO_ZLIB_CTX *ctx;
|
||||
if(!bi) return 0;
|
||||
ctx = (BIO_ZLIB_CTX *)bi->ptr;
|
||||
if(ctx->ibuf)
|
||||
{
|
||||
/* Destroy decompress context */
|
||||
inflateEnd(&ctx->zin);
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
}
|
||||
if(ctx->obuf)
|
||||
{
|
||||
/* Destroy compress context */
|
||||
deflateEnd(&ctx->zout);
|
||||
OPENSSL_free(ctx->obuf);
|
||||
}
|
||||
OPENSSL_free(ctx);
|
||||
bi->ptr = NULL;
|
||||
bi->init = 0;
|
||||
bi->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_zlib_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
BIO_ZLIB_CTX *ctx;
|
||||
int ret;
|
||||
z_stream *zin;
|
||||
if(!out || !outl) return 0;
|
||||
ctx = (BIO_ZLIB_CTX *)b->ptr;
|
||||
zin = &ctx->zin;
|
||||
BIO_clear_retry_flags(b);
|
||||
if(!ctx->ibuf)
|
||||
{
|
||||
ctx->ibuf = OPENSSL_malloc(ctx->ibufsize);
|
||||
if(!ctx->ibuf)
|
||||
{
|
||||
COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
inflateInit(zin);
|
||||
zin->next_in = ctx->ibuf;
|
||||
zin->avail_in = 0;
|
||||
}
|
||||
|
||||
/* Copy output data directly to supplied buffer */
|
||||
zin->next_out = (unsigned char *)out;
|
||||
zin->avail_out = (unsigned int)outl;
|
||||
for(;;)
|
||||
{
|
||||
/* Decompress while data available */
|
||||
while(zin->avail_in)
|
||||
{
|
||||
ret = inflate(zin, 0);
|
||||
if((ret != Z_OK) && (ret != Z_STREAM_END))
|
||||
{
|
||||
COMPerr(COMP_F_BIO_ZLIB_READ,
|
||||
COMP_R_ZLIB_INFLATE_ERROR);
|
||||
ERR_add_error_data(2, "zlib error:",
|
||||
zError(ret));
|
||||
return 0;
|
||||
}
|
||||
/* If EOF or we've read everything then return */
|
||||
if((ret == Z_STREAM_END) || !zin->avail_out)
|
||||
return outl - zin->avail_out;
|
||||
}
|
||||
|
||||
/* No data in input buffer try to read some in,
|
||||
* if an error then return the total data read.
|
||||
*/
|
||||
ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize);
|
||||
if(ret <= 0)
|
||||
{
|
||||
/* Total data read */
|
||||
int tot = outl - zin->avail_out;
|
||||
BIO_copy_next_retry(b);
|
||||
if(ret < 0) return (tot > 0) ? tot : ret;
|
||||
return tot;
|
||||
}
|
||||
zin->avail_in = ret;
|
||||
zin->next_in = ctx->ibuf;
|
||||
}
|
||||
}
|
||||
|
||||
static int bio_zlib_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
BIO_ZLIB_CTX *ctx;
|
||||
int ret;
|
||||
z_stream *zout;
|
||||
if(!in || !inl) return 0;
|
||||
ctx = (BIO_ZLIB_CTX *)b->ptr;
|
||||
if(ctx->odone) return 0;
|
||||
zout = &ctx->zout;
|
||||
BIO_clear_retry_flags(b);
|
||||
if(!ctx->obuf)
|
||||
{
|
||||
ctx->obuf = OPENSSL_malloc(ctx->obufsize);
|
||||
/* Need error here */
|
||||
if(!ctx->obuf)
|
||||
{
|
||||
COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
ctx->optr = ctx->obuf;
|
||||
ctx->ocount = 0;
|
||||
deflateInit(zout, ctx->comp_level);
|
||||
zout->next_out = ctx->obuf;
|
||||
zout->avail_out = ctx->obufsize;
|
||||
}
|
||||
/* Obtain input data directly from supplied buffer */
|
||||
zout->next_in = (void *)in;
|
||||
zout->avail_in = inl;
|
||||
for(;;)
|
||||
{
|
||||
/* If data in output buffer write it first */
|
||||
while(ctx->ocount) {
|
||||
ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
|
||||
if(ret <= 0)
|
||||
{
|
||||
/* Total data written */
|
||||
int tot = inl - zout->avail_in;
|
||||
BIO_copy_next_retry(b);
|
||||
if(ret < 0) return (tot > 0) ? tot : ret;
|
||||
return tot;
|
||||
}
|
||||
ctx->optr += ret;
|
||||
ctx->ocount -= ret;
|
||||
}
|
||||
|
||||
/* Have we consumed all supplied data? */
|
||||
if(!zout->avail_in)
|
||||
return inl;
|
||||
|
||||
/* Compress some more */
|
||||
|
||||
/* Reset buffer */
|
||||
ctx->optr = ctx->obuf;
|
||||
zout->next_out = ctx->obuf;
|
||||
zout->avail_out = ctx->obufsize;
|
||||
/* Compress some more */
|
||||
ret = deflate(zout, 0);
|
||||
if(ret != Z_OK)
|
||||
{
|
||||
COMPerr(COMP_F_BIO_ZLIB_WRITE,
|
||||
COMP_R_ZLIB_DEFLATE_ERROR);
|
||||
ERR_add_error_data(2, "zlib error:", zError(ret));
|
||||
return 0;
|
||||
}
|
||||
ctx->ocount = ctx->obufsize - zout->avail_out;
|
||||
}
|
||||
}
|
||||
|
||||
static int bio_zlib_flush(BIO *b)
|
||||
{
|
||||
BIO_ZLIB_CTX *ctx;
|
||||
int ret;
|
||||
z_stream *zout;
|
||||
ctx = (BIO_ZLIB_CTX *)b->ptr;
|
||||
/* If no data written or already flush show success */
|
||||
if(!ctx->obuf || (ctx->odone && !ctx->ocount)) return 1;
|
||||
zout = &ctx->zout;
|
||||
BIO_clear_retry_flags(b);
|
||||
/* No more input data */
|
||||
zout->next_in = NULL;
|
||||
zout->avail_in = 0;
|
||||
for(;;)
|
||||
{
|
||||
/* If data in output buffer write it first */
|
||||
while(ctx->ocount)
|
||||
{
|
||||
ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
|
||||
if(ret <= 0)
|
||||
{
|
||||
BIO_copy_next_retry(b);
|
||||
return ret;
|
||||
}
|
||||
ctx->optr += ret;
|
||||
ctx->ocount -= ret;
|
||||
}
|
||||
if(ctx->odone) return 1;
|
||||
|
||||
/* Compress some more */
|
||||
|
||||
/* Reset buffer */
|
||||
ctx->optr = ctx->obuf;
|
||||
zout->next_out = ctx->obuf;
|
||||
zout->avail_out = ctx->obufsize;
|
||||
/* Compress some more */
|
||||
ret = deflate(zout, Z_FINISH);
|
||||
if(ret == Z_STREAM_END) ctx->odone = 1;
|
||||
else if(ret != Z_OK)
|
||||
{
|
||||
COMPerr(COMP_F_BIO_ZLIB_FLUSH,
|
||||
COMP_R_ZLIB_DEFLATE_ERROR);
|
||||
ERR_add_error_data(2, "zlib error:", zError(ret));
|
||||
return 0;
|
||||
}
|
||||
ctx->ocount = ctx->obufsize - zout->avail_out;
|
||||
}
|
||||
}
|
||||
|
||||
static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
BIO_ZLIB_CTX *ctx;
|
||||
int ret, *ip;
|
||||
int ibs, obs;
|
||||
if(!b->next_bio) return 0;
|
||||
ctx = (BIO_ZLIB_CTX *)b->ptr;
|
||||
switch (cmd)
|
||||
{
|
||||
|
||||
case BIO_CTRL_RESET:
|
||||
ctx->ocount = 0;
|
||||
ctx->odone = 0;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = bio_zlib_flush(b);
|
||||
if (ret > 0)
|
||||
ret = BIO_flush(b->next_bio);
|
||||
break;
|
||||
|
||||
case BIO_C_SET_BUFF_SIZE:
|
||||
ibs = -1;
|
||||
obs = -1;
|
||||
if (ptr != NULL)
|
||||
{
|
||||
ip = ptr;
|
||||
if (*ip == 0)
|
||||
ibs = (int) num;
|
||||
else
|
||||
obs = (int) num;
|
||||
}
|
||||
else
|
||||
{
|
||||
ibs = (int)num;
|
||||
obs = ibs;
|
||||
}
|
||||
|
||||
if (ibs != -1)
|
||||
{
|
||||
if (ctx->ibuf)
|
||||
{
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
ctx->ibuf = NULL;
|
||||
}
|
||||
ctx->ibufsize = ibs;
|
||||
}
|
||||
|
||||
if (obs != -1)
|
||||
{
|
||||
if (ctx->obuf)
|
||||
{
|
||||
OPENSSL_free(ctx->obuf);
|
||||
ctx->obuf = NULL;
|
||||
}
|
||||
ctx->obufsize = obs;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
BIO_copy_next_retry(b);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
|
||||
{
|
||||
if(!b->next_bio)
|
||||
return 0;
|
||||
return
|
||||
BIO_callback_ctrl(b->next_bio, cmd, fp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -47,6 +47,13 @@ int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
|
||||
unsigned char *in, int ilen);
|
||||
COMP_METHOD *COMP_rle(void );
|
||||
COMP_METHOD *COMP_zlib(void );
|
||||
void COMP_zlib_cleanup(void);
|
||||
|
||||
#ifdef HEADER_BIO_H
|
||||
#ifdef ZLIB
|
||||
BIO_METHOD *BIO_f_zlib(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
/* The following lines are auto generated by the script mkerr.pl. Any changes
|
||||
@ -57,8 +64,15 @@ void ERR_load_COMP_strings(void);
|
||||
/* Error codes for the COMP functions. */
|
||||
|
||||
/* Function codes. */
|
||||
#define COMP_F_BIO_ZLIB_FLUSH 99
|
||||
#define COMP_F_BIO_ZLIB_NEW 100
|
||||
#define COMP_F_BIO_ZLIB_READ 101
|
||||
#define COMP_F_BIO_ZLIB_WRITE 102
|
||||
|
||||
/* Reason codes. */
|
||||
#define COMP_R_ZLIB_DEFLATE_ERROR 99
|
||||
#define COMP_R_ZLIB_INFLATE_ERROR 100
|
||||
#define COMP_R_ZLIB_NOT_SUPPORTED 101
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* crypto/comp/comp_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
|
||||
* Copyright (c) 1999-2007 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
|
||||
@ -70,11 +70,18 @@
|
||||
|
||||
static ERR_STRING_DATA COMP_str_functs[]=
|
||||
{
|
||||
{ERR_FUNC(COMP_F_BIO_ZLIB_FLUSH), "BIO_ZLIB_FLUSH"},
|
||||
{ERR_FUNC(COMP_F_BIO_ZLIB_NEW), "BIO_ZLIB_NEW"},
|
||||
{ERR_FUNC(COMP_F_BIO_ZLIB_READ), "BIO_ZLIB_READ"},
|
||||
{ERR_FUNC(COMP_F_BIO_ZLIB_WRITE), "BIO_ZLIB_WRITE"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA COMP_str_reasons[]=
|
||||
{
|
||||
{ERR_REASON(COMP_R_ZLIB_DEFLATE_ERROR) ,"zlib deflate error"},
|
||||
{ERR_REASON(COMP_R_ZLIB_INFLATE_ERROR) ,"zlib inflate error"},
|
||||
{ERR_REASON(COMP_R_ZLIB_NOT_SUPPORTED) ,"zlib not supported"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
|
@ -76,21 +76,6 @@ clean:
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
dsa_ameth.o: ../../e_os.h ../../include/openssl/asn1.h
|
||||
dsa_ameth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
|
||||
dsa_ameth.o: ../../include/openssl/crypto.h ../../include/openssl/dsa.h
|
||||
dsa_ameth.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
|
||||
dsa_ameth.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
|
||||
dsa_ameth.o: ../../include/openssl/err.h ../../include/openssl/evp.h
|
||||
dsa_ameth.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
dsa_ameth.o: ../../include/openssl/objects.h
|
||||
dsa_ameth.o: ../../include/openssl/opensslconf.h
|
||||
dsa_ameth.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
dsa_ameth.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
|
||||
dsa_ameth.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
dsa_ameth.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
|
||||
dsa_ameth.o: ../../include/openssl/x509_vfy.h ../asn1/asn1_locl.h ../cryptlib.h
|
||||
dsa_ameth.o: dsa_ameth.c
|
||||
dsa_asn1.o: ../../e_os.h ../../include/openssl/asn1.h
|
||||
dsa_asn1.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
|
||||
dsa_asn1.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
|
||||
|
@ -60,6 +60,9 @@
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/dsa.h>
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
#include <openssl/cms.h>
|
||||
#endif
|
||||
#include "asn1_locl.h"
|
||||
|
||||
static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
|
||||
@ -550,6 +553,24 @@ static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
|
||||
}
|
||||
return 1;
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
case ASN1_PKEY_CTRL_CMS_SIGN:
|
||||
if (arg1 == 0)
|
||||
{
|
||||
int snid, hnid;
|
||||
X509_ALGOR *alg1, *alg2;
|
||||
CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
|
||||
if (alg1 == NULL || alg1->algorithm == NULL)
|
||||
return -1;
|
||||
hnid = OBJ_obj2nid(alg1->algorithm);
|
||||
if (hnid == NID_undef)
|
||||
return -1;
|
||||
if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
|
||||
return -1;
|
||||
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha1;
|
||||
|
@ -195,6 +195,7 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_PKCS7_SIGN:
|
||||
case EVP_PKEY_CTRL_CMS_SIGN:
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
|
@ -59,6 +59,9 @@
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/ec.h>
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
#include <openssl/cms.h>
|
||||
#endif
|
||||
#include "asn1_locl.h"
|
||||
|
||||
static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
|
||||
@ -590,6 +593,25 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
|
||||
}
|
||||
return 1;
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
case ASN1_PKEY_CTRL_CMS_SIGN:
|
||||
if (arg1 == 0)
|
||||
{
|
||||
int snid, hnid;
|
||||
X509_ALGOR *alg1, *alg2;
|
||||
CMS_SignerInfo_get0_algs(arg2, NULL, NULL,
|
||||
&alg1, &alg2);
|
||||
if (alg1 == NULL || alg1->algorithm == NULL)
|
||||
return -1;
|
||||
hnid = OBJ_obj2nid(alg1->algorithm);
|
||||
if (hnid == NID_undef)
|
||||
return -1;
|
||||
if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
|
||||
return -1;
|
||||
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha1;
|
||||
|
@ -235,6 +235,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
/* Default behaviour is OK */
|
||||
case EVP_PKEY_CTRL_PKCS7_SIGN:
|
||||
case EVP_PKEY_CTRL_CMS_SIGN:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
|
@ -83,23 +83,24 @@ err.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
|
||||
err.o: ../cryptlib.h err.c
|
||||
err_all.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
|
||||
err_all.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
|
||||
err_all.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
|
||||
err_all.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h
|
||||
err_all.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h
|
||||
err_all.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
|
||||
err_all.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
|
||||
err_all.o: ../../include/openssl/err.h ../../include/openssl/evp.h
|
||||
err_all.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
|
||||
err_all.o: ../../include/openssl/objects.h ../../include/openssl/ocsp.h
|
||||
err_all.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
|
||||
err_all.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem2.h
|
||||
err_all.o: ../../include/openssl/pkcs12.h ../../include/openssl/pkcs7.h
|
||||
err_all.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h
|
||||
err_all.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
|
||||
err_all.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
|
||||
err_all.o: ../../include/openssl/ts.h ../../include/openssl/ui.h
|
||||
err_all.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
|
||||
err_all.o: ../../include/openssl/x509v3.h err_all.c
|
||||
err_all.o: ../../include/openssl/comp.h ../../include/openssl/conf.h
|
||||
err_all.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h
|
||||
err_all.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h
|
||||
err_all.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
|
||||
err_all.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
|
||||
err_all.o: ../../include/openssl/engine.h ../../include/openssl/err.h
|
||||
err_all.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
|
||||
err_all.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
|
||||
err_all.o: ../../include/openssl/ocsp.h ../../include/openssl/opensslconf.h
|
||||
err_all.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
|
||||
err_all.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs12.h
|
||||
err_all.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
|
||||
err_all.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
|
||||
err_all.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
|
||||
err_all.o: ../../include/openssl/symhacks.h ../../include/openssl/ts.h
|
||||
err_all.o: ../../include/openssl/ui.h ../../include/openssl/x509.h
|
||||
err_all.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h
|
||||
err_all.o: err_all.c
|
||||
err_prn.o: ../../e_os.h ../../include/openssl/bio.h
|
||||
err_prn.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
|
||||
err_prn.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
|
||||
|
@ -151,6 +151,7 @@ static ERR_STRING_DATA ERR_str_libraries[]=
|
||||
{ERR_PACK(ERR_LIB_ENGINE,0,0) ,"engine routines"},
|
||||
{ERR_PACK(ERR_LIB_OCSP,0,0) ,"OCSP routines"},
|
||||
{ERR_PACK(ERR_LIB_HMAC,0,0) ,"HMAC routines"},
|
||||
{ERR_PACK(ERR_LIB_CMS,0,0) ,"CMS routines"},
|
||||
{0,NULL},
|
||||
};
|
||||
|
||||
|
@ -196,6 +196,7 @@ typedef struct err_state_st
|
||||
#define ERR_LIB_STORE 44
|
||||
#define ERR_LIB_TS 45
|
||||
#define ERR_LIB_HMAC 46
|
||||
#define ERR_LIB_CMS 47
|
||||
|
||||
#define ERR_LIB_USER 128
|
||||
|
||||
@ -229,6 +230,7 @@ typedef struct err_state_st
|
||||
#define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__)
|
||||
#define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),__FILE__,__LINE__)
|
||||
#define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),__FILE__,__LINE__)
|
||||
#define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__)
|
||||
|
||||
/* Borland C seems too stupid to be able to shift and do longs in
|
||||
* the pre-processor :-( */
|
||||
|
@ -64,6 +64,7 @@
|
||||
#endif
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/comp.h>
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
#include <openssl/rsa.h>
|
||||
#endif
|
||||
@ -95,6 +96,9 @@
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ts.h>
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
#include <openssl/cms.h>
|
||||
#endif
|
||||
|
||||
void ERR_load_crypto_strings(void)
|
||||
{
|
||||
@ -118,6 +122,7 @@ void ERR_load_crypto_strings(void)
|
||||
ERR_load_ASN1_strings();
|
||||
ERR_load_CONF_strings();
|
||||
ERR_load_CRYPTO_strings();
|
||||
ERR_load_COMP_strings();
|
||||
#ifndef OPENSSL_NO_EC
|
||||
ERR_load_EC_strings();
|
||||
#endif
|
||||
@ -140,5 +145,8 @@ void ERR_load_crypto_strings(void)
|
||||
#endif
|
||||
ERR_load_OCSP_strings();
|
||||
ERR_load_UI_strings();
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
ERR_load_CMS_strings();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ L ECDH crypto/ecdh/ecdh.h crypto/ecdh/ech_err.c
|
||||
L STORE crypto/store/store.h crypto/store/str_err.c
|
||||
L TS crypto/ts/ts.h crypto/ts/ts_err.c
|
||||
L HMAC crypto/hmac/hmac.h crypto/hmac/hmac_err.c
|
||||
L CMS crypto/cms/cms.h crypto/cms/cms_err.c
|
||||
|
||||
# additional header files to be scanned for function names
|
||||
L NONE crypto/x509/x509_vfy.h NONE
|
||||
|
@ -927,6 +927,8 @@ void EVP_PBE_cleanup(void);
|
||||
#define ASN1_PKEY_CTRL_PKCS7_SIGN 0x1
|
||||
#define ASN1_PKEY_CTRL_PKCS7_ENCRYPT 0x2
|
||||
#define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3
|
||||
#define ASN1_PKEY_CTRL_CMS_SIGN 0x5
|
||||
#define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7
|
||||
|
||||
int EVP_PKEY_asn1_get_count(void);
|
||||
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
|
||||
@ -1019,6 +1021,10 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
|
||||
/* Used by GOST key encryption in TLS */
|
||||
#define EVP_PKEY_CTRL_SET_IV 8
|
||||
|
||||
#define EVP_PKEY_CTRL_CMS_ENCRYPT 9
|
||||
#define EVP_PKEY_CTRL_CMS_DECRYPT 10
|
||||
#define EVP_PKEY_CTRL_CMS_SIGN 11
|
||||
|
||||
#define EVP_PKEY_ALG_CTRL 0x1000
|
||||
|
||||
|
||||
|
@ -82,7 +82,7 @@ static const EVP_MD sha1_md=
|
||||
NID_sha1,
|
||||
NID_sha1WithRSAEncryption,
|
||||
SHA_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
init,
|
||||
update,
|
||||
final,
|
||||
@ -119,7 +119,7 @@ static const EVP_MD sha224_md=
|
||||
NID_sha224,
|
||||
NID_sha224WithRSAEncryption,
|
||||
SHA224_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
init224,
|
||||
update256,
|
||||
final256,
|
||||
@ -138,7 +138,7 @@ static const EVP_MD sha256_md=
|
||||
NID_sha256,
|
||||
NID_sha256WithRSAEncryption,
|
||||
SHA256_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
init256,
|
||||
update256,
|
||||
final256,
|
||||
@ -169,7 +169,7 @@ static const EVP_MD sha384_md=
|
||||
NID_sha384,
|
||||
NID_sha384WithRSAEncryption,
|
||||
SHA384_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
init384,
|
||||
update512,
|
||||
final512,
|
||||
@ -188,7 +188,7 @@ static const EVP_MD sha512_md=
|
||||
NID_sha512,
|
||||
NID_sha512WithRSAEncryption,
|
||||
SHA512_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
|
||||
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
init512,
|
||||
update512,
|
||||
final512,
|
||||
|
@ -134,6 +134,7 @@ extern "C" {
|
||||
#define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
|
||||
#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"
|
||||
#define PEM_STRING_PARAMETERS "PARAMETERS"
|
||||
#define PEM_STRING_CMS "CMS"
|
||||
|
||||
/* Note that this structure is initialised by PEM_SealInit and cleaned up
|
||||
by PEM_SealFinal (at least for now) */
|
||||
|
@ -256,6 +256,14 @@ static int check_pem(const char *nm, const char *name)
|
||||
if(!strcmp(nm, PEM_STRING_X509) &&
|
||||
!strcmp(name, PEM_STRING_PKCS7)) return 1;
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
if(!strcmp(nm, PEM_STRING_X509) &&
|
||||
!strcmp(name, PEM_STRING_CMS)) return 1;
|
||||
/* Allow CMS to be read from PKCS#7 headers */
|
||||
if(!strcmp(nm, PEM_STRING_PKCS7) &&
|
||||
!strcmp(name, PEM_STRING_CMS)) return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* bio_pk7.c */
|
||||
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
* 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
|
||||
@ -50,10 +50,6 @@
|
||||
* 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 <openssl/asn1.h>
|
||||
@ -65,165 +61,9 @@
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
/* Highly experiemental PKCS#7 BIO support routines */
|
||||
|
||||
/* The usage is quite simple, initialize a PKCS7 structure,
|
||||
* get a BIO from it then any data written through the BIO
|
||||
* will end up translated to PKCS#7 format on the fly.
|
||||
* The data is streamed out and does *not* need to be
|
||||
* all held in memory at once.
|
||||
*
|
||||
* When the BIO is flushed the output is finalized and any
|
||||
* signatures etc written out.
|
||||
*
|
||||
* The BIO is a 'proper' BIO and can handle non blocking I/O
|
||||
* correctly.
|
||||
*
|
||||
* The usage is simple. The implementation is *not*...
|
||||
*/
|
||||
|
||||
/* BIO support data stored in the ASN1 BIO ex_arg */
|
||||
|
||||
typedef struct pkcs7_aux_st
|
||||
{
|
||||
/* PKCS7 structure this BIO refers to */
|
||||
PKCS7 *p7;
|
||||
/* Top of the BIO chain */
|
||||
BIO *p7bio;
|
||||
/* Output BIO */
|
||||
BIO *out;
|
||||
/* Boundary where content is inserted */
|
||||
unsigned char **boundary;
|
||||
/* DER buffer start */
|
||||
unsigned char *derbuf;
|
||||
} PKCS7_SUPPORT;
|
||||
|
||||
static int pkcs7_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int pkcs7_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int pkcs7_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int pkcs7_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
/* Streaming encode support for PKCS#7 */
|
||||
|
||||
BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7)
|
||||
{
|
||||
PKCS7_SUPPORT *p7aux = NULL;
|
||||
BIO *p7bio = NULL;
|
||||
BIO *asn_bio = NULL;
|
||||
unsigned char **boundary;
|
||||
p7aux = OPENSSL_malloc(sizeof(PKCS7_SUPPORT));
|
||||
asn_bio = BIO_new(BIO_f_asn1());
|
||||
|
||||
/* ASN1 bio needs to be next to output BIO */
|
||||
|
||||
out = BIO_push(asn_bio, out);
|
||||
|
||||
if (!p7aux || !asn_bio || !out)
|
||||
goto err;
|
||||
|
||||
BIO_asn1_set_prefix(asn_bio, pkcs7_prefix, pkcs7_prefix_free);
|
||||
BIO_asn1_set_suffix(asn_bio, pkcs7_suffix, pkcs7_suffix_free);
|
||||
|
||||
/* Now initialize BIO for PKCS#7 output */
|
||||
|
||||
p7bio = PKCS7_dataInit(p7, out);
|
||||
if (!p7bio || !PKCS7_stream(&boundary, p7))
|
||||
goto err;
|
||||
|
||||
p7aux->p7 = p7;
|
||||
p7aux->p7bio = p7bio;
|
||||
p7aux->boundary = boundary;
|
||||
p7aux->out = out;
|
||||
|
||||
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, p7aux);
|
||||
|
||||
return p7bio;
|
||||
|
||||
err:
|
||||
if (p7bio)
|
||||
BIO_free(p7bio);
|
||||
if (asn_bio)
|
||||
BIO_free(asn_bio);
|
||||
if (p7aux)
|
||||
OPENSSL_free(p7aux);
|
||||
return NULL;
|
||||
return BIO_new_NDEF(out, (ASN1_VALUE *)p7, ASN1_ITEM_rptr(PKCS7));
|
||||
}
|
||||
|
||||
static int pkcs7_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
PKCS7_SUPPORT *p7aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
p7aux = *(PKCS7_SUPPORT **)parg;
|
||||
|
||||
derlen = i2d_PKCS7_NDEF(p7aux->p7, NULL);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
p7aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
i2d_PKCS7_NDEF(p7aux->p7, &p);
|
||||
|
||||
if (!*p7aux->boundary)
|
||||
return 0;
|
||||
|
||||
*plen = *p7aux->boundary - *pbuf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkcs7_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
PKCS7_SUPPORT *p7aux;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
p7aux = *(PKCS7_SUPPORT **)parg;
|
||||
|
||||
if (p7aux->derbuf)
|
||||
OPENSSL_free(p7aux->derbuf);
|
||||
|
||||
p7aux->derbuf = NULL;
|
||||
*pbuf = NULL;
|
||||
*plen = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkcs7_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
PKCS7_SUPPORT **pp7aux = (PKCS7_SUPPORT **)parg;
|
||||
if (!pkcs7_prefix_free(b, pbuf, plen, parg))
|
||||
return 0;
|
||||
OPENSSL_free(*pp7aux);
|
||||
*pp7aux = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkcs7_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
PKCS7_SUPPORT *p7aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
p7aux = *(PKCS7_SUPPORT **)parg;
|
||||
|
||||
/* Finalize structures */
|
||||
PKCS7_dataFinal(p7aux->p7, p7aux->p7bio);
|
||||
|
||||
derlen = i2d_PKCS7_NDEF(p7aux->p7, NULL);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
p7aux->derbuf = p;
|
||||
i2d_PKCS7_NDEF(p7aux->p7, &p);
|
||||
if (!*p7aux->boundary)
|
||||
return 0;
|
||||
*pbuf = *p7aux->boundary;
|
||||
*plen = derlen - (*p7aux->boundary - p7aux->derbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,10 +77,42 @@ ASN1_ADB(PKCS7) = {
|
||||
ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP_OPT(PKCS7, d.encrypted, PKCS7_ENCRYPT, 0))
|
||||
} ASN1_ADB_END(PKCS7, 0, type, 0, &p7default_tt, NULL);
|
||||
|
||||
ASN1_NDEF_SEQUENCE(PKCS7) = {
|
||||
/* PKCS#7 streaming support */
|
||||
static int pk7_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
ASN1_STREAM_ARG *sarg = exarg;
|
||||
PKCS7 *p7;
|
||||
if (pval)
|
||||
p7 = (PKCS7 *)*pval;
|
||||
else
|
||||
p7 = NULL;
|
||||
switch(operation)
|
||||
{
|
||||
|
||||
case ASN1_OP_STREAM_PRE:
|
||||
if (PKCS7_stream(&sarg->boundary, p7) <= 0)
|
||||
return 0;
|
||||
case ASN1_OP_DETACHED_PRE:
|
||||
sarg->ndef_bio = PKCS7_dataInit(p7, sarg->out);
|
||||
if (!sarg->ndef_bio)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ASN1_OP_STREAM_POST:
|
||||
case ASN1_OP_DETACHED_POST:
|
||||
if (PKCS7_dataFinal(p7, sarg->ndef_bio) <= 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_NDEF_SEQUENCE_cb(PKCS7, pk7_cb) = {
|
||||
ASN1_SIMPLE(PKCS7, type, ASN1_OBJECT),
|
||||
ASN1_ADB_OBJECT(PKCS7)
|
||||
}ASN1_NDEF_SEQUENCE_END(PKCS7)
|
||||
}ASN1_NDEF_SEQUENCE_END_cb(PKCS7, PKCS7)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7)
|
||||
IMPLEMENT_ASN1_NDEF_FUNCTION(PKCS7)
|
||||
|
@ -66,10 +66,6 @@
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
ASN1_ITEM_TEMPLATE(X509_ALGORS) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
|
||||
ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
|
||||
|
||||
int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK_OF(X509_ALGOR) *cap)
|
||||
{
|
||||
ASN1_STRING *seq;
|
||||
|
@ -50,10 +50,6 @@
|
||||
* 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 <stdio.h>
|
||||
@ -61,862 +57,41 @@
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
/* MIME and related routines */
|
||||
|
||||
/* MIME format structures
|
||||
* Note that all are translated to lower case apart from
|
||||
* parameter values. Quotes are stripped off
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *param_name; /* Param name e.g. "micalg" */
|
||||
char *param_value; /* Param value e.g. "sha1" */
|
||||
} MIME_PARAM;
|
||||
|
||||
DECLARE_STACK_OF(MIME_PARAM)
|
||||
IMPLEMENT_STACK_OF(MIME_PARAM)
|
||||
|
||||
typedef struct {
|
||||
char *name; /* Name of line e.g. "content-type" */
|
||||
char *value; /* Value of line e.g. "text/plain" */
|
||||
STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */
|
||||
} MIME_HEADER;
|
||||
|
||||
DECLARE_STACK_OF(MIME_HEADER)
|
||||
IMPLEMENT_STACK_OF(MIME_HEADER)
|
||||
|
||||
static int pkcs7_output_data(BIO *bio, BIO *data, PKCS7 *p7, int flags);
|
||||
static int B64_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *in, int flags);
|
||||
static PKCS7 *B64_read_PKCS7(BIO *bio);
|
||||
static char * strip_ends(char *name);
|
||||
static char * strip_start(char *name);
|
||||
static char * strip_end(char *name);
|
||||
static MIME_HEADER *mime_hdr_new(char *name, char *value);
|
||||
static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value);
|
||||
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
|
||||
static int mime_hdr_cmp(const MIME_HEADER * const *a,
|
||||
const MIME_HEADER * const *b);
|
||||
static int mime_param_cmp(const MIME_PARAM * const *a,
|
||||
const MIME_PARAM * const *b);
|
||||
static void mime_param_free(MIME_PARAM *param);
|
||||
static int mime_bound_check(char *line, int linelen, char *bound, int blen);
|
||||
static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
|
||||
static int strip_eol(char *linebuf, int *plen);
|
||||
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name);
|
||||
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name);
|
||||
static void mime_hdr_free(MIME_HEADER *hdr);
|
||||
|
||||
#define MAX_SMLEN 1024
|
||||
#define mime_debug(x) /* x */
|
||||
|
||||
/* Output a PKCS#7 structure in BER format streaming if necessary */
|
||||
/* PKCS#7 wrappers round generalised stream and MIME routines */
|
||||
|
||||
int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags)
|
||||
{
|
||||
/* If streaming create stream BIO and copy all content through it */
|
||||
if (flags & PKCS7_STREAM)
|
||||
{
|
||||
BIO *bio, *tbio;
|
||||
bio = BIO_new_PKCS7(out, p7);
|
||||
if (!bio)
|
||||
{
|
||||
PKCS7err(PKCS7_F_I2D_PKCS7_BIO_STREAM,ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
SMIME_crlf_copy(in, bio, flags);
|
||||
(void)BIO_flush(bio);
|
||||
/* Free up successive BIOs until we hit the old output BIO */
|
||||
do
|
||||
{
|
||||
tbio = BIO_pop(bio);
|
||||
BIO_free(bio);
|
||||
bio = tbio;
|
||||
} while (bio != out);
|
||||
}
|
||||
/* else just write out PKCS7 structure which will have all content
|
||||
* stored internally
|
||||
*/
|
||||
else
|
||||
i2d_PKCS7_bio(out, p7);
|
||||
return 1;
|
||||
return i2d_ASN1_bio_stream(out, (ASN1_VALUE *)p7, in, flags,
|
||||
ASN1_ITEM_rptr(PKCS7));
|
||||
}
|
||||
|
||||
/* Base 64 read and write of PKCS#7 structure */
|
||||
|
||||
static int B64_write_PKCS7(BIO *out, PKCS7 *p7, BIO *in, int flags)
|
||||
{
|
||||
BIO *b64;
|
||||
int r;
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
if(!b64)
|
||||
{
|
||||
PKCS7err(PKCS7_F_B64_WRITE_PKCS7,ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
/* prepend the b64 BIO so all data is base64 encoded.
|
||||
*/
|
||||
out = BIO_push(b64, out);
|
||||
r = i2d_PKCS7_bio_stream(out, p7, in, flags);
|
||||
(void)BIO_flush(out);
|
||||
BIO_pop(out);
|
||||
BIO_free(b64);
|
||||
return r;
|
||||
}
|
||||
|
||||
static PKCS7 *B64_read_PKCS7(BIO *bio)
|
||||
{
|
||||
BIO *b64;
|
||||
PKCS7 *p7;
|
||||
if(!(b64 = BIO_new(BIO_f_base64()))) {
|
||||
PKCS7err(PKCS7_F_B64_READ_PKCS7,ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
bio = BIO_push(b64, bio);
|
||||
if(!(p7 = d2i_PKCS7_bio(bio, NULL)))
|
||||
PKCS7err(PKCS7_F_B64_READ_PKCS7,PKCS7_R_DECODE_ERROR);
|
||||
(void)BIO_flush(bio);
|
||||
bio = BIO_pop(bio);
|
||||
BIO_free(b64);
|
||||
return p7;
|
||||
}
|
||||
|
||||
/* Streaming PKCS#7 PEM write */
|
||||
|
||||
int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags)
|
||||
{
|
||||
int r;
|
||||
BIO_puts(out, "-----BEGIN PKCS7-----\n");
|
||||
r = B64_write_PKCS7(out, p7, in, flags);
|
||||
BIO_puts(out, "-----END PKCS7-----\n");
|
||||
return r;
|
||||
return PEM_write_bio_ASN1_stream(out, (ASN1_VALUE *) p7, in, flags,
|
||||
"PKCS7",
|
||||
ASN1_ITEM_rptr(PKCS7));
|
||||
}
|
||||
|
||||
/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
|
||||
|
||||
static int pk7_write_micalg(BIO *out, PKCS7 *p7)
|
||||
{
|
||||
STACK_OF(X509_ALGOR) *mdalgs;
|
||||
const EVP_MD *md;
|
||||
int i, have_unknown = 0, write_comma, ret = 0, md_nid;
|
||||
mdalgs = p7->d.sign->md_algs;
|
||||
have_unknown = 0;
|
||||
write_comma = 0;
|
||||
for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++)
|
||||
{
|
||||
if (write_comma)
|
||||
BIO_write(out, ",", 1);
|
||||
write_comma = 1;
|
||||
md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
|
||||
md = EVP_get_digestbynid(md_nid);
|
||||
if (md && md->md_ctrl)
|
||||
{
|
||||
int rv;
|
||||
char *micstr;
|
||||
rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr);
|
||||
if (rv > 0)
|
||||
{
|
||||
BIO_puts(out, micstr);
|
||||
OPENSSL_free(micstr);
|
||||
continue;
|
||||
}
|
||||
if (rv != -2)
|
||||
goto err;
|
||||
}
|
||||
switch(md_nid)
|
||||
{
|
||||
case NID_sha1:
|
||||
BIO_puts(out, "sha1");
|
||||
break;
|
||||
|
||||
case NID_md5:
|
||||
BIO_puts(out, "md5");
|
||||
break;
|
||||
|
||||
case NID_sha256:
|
||||
BIO_puts(out, "sha-256");
|
||||
break;
|
||||
|
||||
case NID_sha384:
|
||||
BIO_puts(out, "sha-384");
|
||||
break;
|
||||
|
||||
case NID_sha512:
|
||||
BIO_puts(out, "sha-512");
|
||||
break;
|
||||
|
||||
case NID_id_GostR3411_94:
|
||||
BIO_puts(out, "gostr3411-94");
|
||||
goto err;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (have_unknown)
|
||||
write_comma = 0;
|
||||
else
|
||||
{
|
||||
BIO_puts(out, "unknown");
|
||||
have_unknown = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* SMIME sender */
|
||||
|
||||
int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
|
||||
{
|
||||
char bound[33], c;
|
||||
int i;
|
||||
char *mime_prefix, *mime_eol, *msg_type=NULL;
|
||||
if (flags & PKCS7_NOOLDMIMETYPE)
|
||||
mime_prefix = "application/pkcs7-";
|
||||
else
|
||||
mime_prefix = "application/x-pkcs7-";
|
||||
|
||||
if (flags & PKCS7_CRLFEOL)
|
||||
mime_eol = "\r\n";
|
||||
else
|
||||
mime_eol = "\n";
|
||||
if((flags & PKCS7_DETACHED) && data) {
|
||||
/* We want multipart/signed */
|
||||
/* Generate a random boundary */
|
||||
RAND_pseudo_bytes((unsigned char *)bound, 32);
|
||||
for(i = 0; i < 32; i++) {
|
||||
c = bound[i] & 0xf;
|
||||
if(c < 10) c += '0';
|
||||
else c += 'A' - 10;
|
||||
bound[i] = c;
|
||||
}
|
||||
bound[32] = 0;
|
||||
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Type: multipart/signed;");
|
||||
BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
|
||||
BIO_puts(bio, " micalg=\"");
|
||||
pk7_write_micalg(bio, p7);
|
||||
BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
|
||||
bound, mime_eol, mime_eol);
|
||||
BIO_printf(bio, "This is an S/MIME signed message%s%s",
|
||||
mime_eol, mime_eol);
|
||||
/* Now write out the first part */
|
||||
BIO_printf(bio, "------%s%s", bound, mime_eol);
|
||||
pkcs7_output_data(bio, data, p7, flags);
|
||||
BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
|
||||
|
||||
/* Headers for signature */
|
||||
|
||||
BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
|
||||
BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Transfer-Encoding: base64%s",
|
||||
mime_eol);
|
||||
BIO_printf(bio, "Content-Disposition: attachment;");
|
||||
BIO_printf(bio, " filename=\"smime.p7s\"%s%s",
|
||||
mime_eol, mime_eol);
|
||||
B64_write_PKCS7(bio, p7, NULL, 0);
|
||||
BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound,
|
||||
mime_eol, mime_eol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Determine smime-type header */
|
||||
|
||||
if (PKCS7_type_is_enveloped(p7))
|
||||
msg_type = "enveloped-data";
|
||||
else if (PKCS7_type_is_signed(p7))
|
||||
{
|
||||
/* If we have any signers it is signed-data otherwise
|
||||
* certs-only.
|
||||
*/
|
||||
STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
|
||||
sinfos = PKCS7_get_signer_info(p7);
|
||||
if (sk_PKCS7_SIGNER_INFO_num(sinfos) > 0)
|
||||
msg_type = "signed-data";
|
||||
else
|
||||
msg_type = "certs-only";
|
||||
}
|
||||
else
|
||||
flags &= ~PKCS7_STREAM;
|
||||
/* MIME headers */
|
||||
BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Disposition: attachment;");
|
||||
BIO_printf(bio, " filename=\"smime.p7m\"%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
|
||||
if (msg_type)
|
||||
BIO_printf(bio, " smime-type=%s;", msg_type);
|
||||
BIO_printf(bio, " name=\"smime.p7m\"%s", mime_eol);
|
||||
BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
|
||||
mime_eol, mime_eol);
|
||||
B64_write_PKCS7(bio, p7, data, flags);
|
||||
BIO_printf(bio, "%s", mime_eol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle output of PKCS#7 data */
|
||||
|
||||
|
||||
static int pkcs7_output_data(BIO *out, BIO *data, PKCS7 *p7, int flags)
|
||||
{
|
||||
BIO *tmpbio, *p7bio;
|
||||
STACK_OF(X509_ALGOR) *mdalgs;
|
||||
int ctype_nid = OBJ_obj2nid(p7->type);
|
||||
if (ctype_nid == NID_pkcs7_signed)
|
||||
mdalgs = p7->d.sign->md_algs;
|
||||
else
|
||||
mdalgs = NULL;
|
||||
|
||||
if (!(flags & PKCS7_STREAM))
|
||||
{
|
||||
SMIME_crlf_copy(data, out, flags);
|
||||
return 1;
|
||||
}
|
||||
flags ^= SMIME_OLDMIME;
|
||||
|
||||
/* Partial sign operation */
|
||||
|
||||
/* Initialize sign operation */
|
||||
p7bio = PKCS7_dataInit(p7, out);
|
||||
|
||||
/* Copy data across, computing digests etc */
|
||||
SMIME_crlf_copy(data, p7bio, flags);
|
||||
|
||||
/* Must be detached */
|
||||
PKCS7_set_detached(p7, 1);
|
||||
|
||||
/* Finalize signatures */
|
||||
PKCS7_dataFinal(p7, p7bio);
|
||||
|
||||
/* Now remove any digests prepended to the BIO */
|
||||
|
||||
while (p7bio != out)
|
||||
{
|
||||
tmpbio = BIO_pop(p7bio);
|
||||
BIO_free(p7bio);
|
||||
p7bio = tmpbio;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
return SMIME_write_ASN1(bio, (ASN1_VALUE *)p7, data, flags,
|
||||
ctype_nid, mdalgs,
|
||||
ASN1_ITEM_rptr(PKCS7));
|
||||
}
|
||||
|
||||
/* SMIME reader: handle multipart/signed and opaque signing.
|
||||
* in multipart case the content is placed in a memory BIO
|
||||
* pointed to by "bcont". In opaque this is set to NULL
|
||||
*/
|
||||
|
||||
PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
|
||||
{
|
||||
BIO *p7in;
|
||||
STACK_OF(MIME_HEADER) *headers = NULL;
|
||||
STACK_OF(BIO) *parts = NULL;
|
||||
MIME_HEADER *hdr;
|
||||
MIME_PARAM *prm;
|
||||
PKCS7 *p7;
|
||||
int ret;
|
||||
|
||||
if(bcont) *bcont = NULL;
|
||||
|
||||
if (!(headers = mime_parse_hdr(bio))) {
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_MIME_PARSE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_CONTENT_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle multipart/signed */
|
||||
|
||||
if(!strcmp(hdr->value, "multipart/signed")) {
|
||||
/* Split into two parts */
|
||||
prm = mime_param_find(hdr, "boundary");
|
||||
if(!prm || !prm->param_value) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BOUNDARY);
|
||||
return NULL;
|
||||
}
|
||||
ret = multi_split(bio, prm->param_value, &parts);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
if(!ret || (sk_BIO_num(parts) != 2) ) {
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BODY_FAILURE);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parse the signature piece */
|
||||
p7in = sk_BIO_value(parts, 1);
|
||||
|
||||
if (!(headers = mime_parse_hdr(p7in))) {
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_MIME_SIG_PARSE_ERROR);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get content type */
|
||||
|
||||
if(!(hdr = mime_hdr_find(headers, "content-type")) ||
|
||||
!hdr->value) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_SIG_CONTENT_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(strcmp(hdr->value, "application/x-pkcs7-signature") &&
|
||||
strcmp(hdr->value, "application/pkcs7-signature")) {
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_SIG_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
/* Read in PKCS#7 */
|
||||
if(!(p7 = B64_read_PKCS7(p7in))) {
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_PKCS7_SIG_PARSE_ERROR);
|
||||
sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(bcont) {
|
||||
*bcont = sk_BIO_value(parts, 0);
|
||||
BIO_free(p7in);
|
||||
sk_BIO_free(parts);
|
||||
} else sk_BIO_pop_free(parts, BIO_vfree);
|
||||
return p7;
|
||||
}
|
||||
|
||||
/* OK, if not multipart/signed try opaque signature */
|
||||
|
||||
if (strcmp (hdr->value, "application/x-pkcs7-mime") &&
|
||||
strcmp (hdr->value, "application/pkcs7-mime")) {
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
|
||||
if(!(p7 = B64_read_PKCS7(bio))) {
|
||||
PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_PKCS7_PARSE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
return p7;
|
||||
|
||||
}
|
||||
|
||||
/* Copy text from one BIO to another making the output CRLF at EOL */
|
||||
int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
|
||||
{
|
||||
BIO *bf;
|
||||
char eol;
|
||||
int len;
|
||||
char linebuf[MAX_SMLEN];
|
||||
/* Buffer output so we don't write one line at a time. This is
|
||||
* useful when streaming as we don't end up with one OCTET STRING
|
||||
* per line.
|
||||
*/
|
||||
bf = BIO_new(BIO_f_buffer());
|
||||
if (!bf)
|
||||
return 0;
|
||||
out = BIO_push(bf, out);
|
||||
if(flags & PKCS7_BINARY)
|
||||
{
|
||||
while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
|
||||
BIO_write(out, linebuf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(flags & PKCS7_TEXT)
|
||||
BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
|
||||
while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0)
|
||||
{
|
||||
eol = strip_eol(linebuf, &len);
|
||||
if (len)
|
||||
BIO_write(out, linebuf, len);
|
||||
if(eol) BIO_write(out, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
(void)BIO_flush(out);
|
||||
BIO_pop(out);
|
||||
BIO_free(bf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Strip off headers if they are text/plain */
|
||||
int SMIME_text(BIO *in, BIO *out)
|
||||
{
|
||||
char iobuf[4096];
|
||||
int len;
|
||||
STACK_OF(MIME_HEADER) *headers;
|
||||
MIME_HEADER *hdr;
|
||||
|
||||
if (!(headers = mime_parse_hdr(in))) {
|
||||
PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_PARSE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
|
||||
PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_NO_CONTENT_TYPE);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp (hdr->value, "text/plain")) {
|
||||
PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_INVALID_MIME_TYPE);
|
||||
ERR_add_error_data(2, "type: ", hdr->value);
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
return 0;
|
||||
}
|
||||
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
|
||||
while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
|
||||
BIO_write(out, iobuf, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Split a multipart/XXX message body into component parts: result is
|
||||
* canonical parts in a STACK of bios
|
||||
*/
|
||||
|
||||
static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
|
||||
{
|
||||
char linebuf[MAX_SMLEN];
|
||||
int len, blen;
|
||||
int eol = 0, next_eol = 0;
|
||||
BIO *bpart = NULL;
|
||||
STACK_OF(BIO) *parts;
|
||||
char state, part, first;
|
||||
|
||||
blen = strlen(bound);
|
||||
part = 0;
|
||||
state = 0;
|
||||
first = 1;
|
||||
parts = sk_BIO_new_null();
|
||||
*ret = parts;
|
||||
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
|
||||
state = mime_bound_check(linebuf, len, bound, blen);
|
||||
if(state == 1) {
|
||||
first = 1;
|
||||
part++;
|
||||
} else if(state == 2) {
|
||||
sk_BIO_push(parts, bpart);
|
||||
return 1;
|
||||
} else if(part) {
|
||||
/* Strip CR+LF from linebuf */
|
||||
next_eol = strip_eol(linebuf, &len);
|
||||
if(first) {
|
||||
first = 0;
|
||||
if(bpart) sk_BIO_push(parts, bpart);
|
||||
bpart = BIO_new(BIO_s_mem());
|
||||
BIO_set_mem_eof_return(bpart, 0);
|
||||
} else if (eol)
|
||||
BIO_write(bpart, "\r\n", 2);
|
||||
eol = next_eol;
|
||||
if (len)
|
||||
BIO_write(bpart, linebuf, len);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the big one: parse MIME header lines up to message body */
|
||||
|
||||
#define MIME_INVALID 0
|
||||
#define MIME_START 1
|
||||
#define MIME_TYPE 2
|
||||
#define MIME_NAME 3
|
||||
#define MIME_VALUE 4
|
||||
#define MIME_QUOTE 5
|
||||
#define MIME_COMMENT 6
|
||||
|
||||
|
||||
static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
|
||||
{
|
||||
char *p, *q, c;
|
||||
char *ntmp;
|
||||
char linebuf[MAX_SMLEN];
|
||||
MIME_HEADER *mhdr = NULL;
|
||||
STACK_OF(MIME_HEADER) *headers;
|
||||
int len, state, save_state = 0;
|
||||
|
||||
headers = sk_MIME_HEADER_new(mime_hdr_cmp);
|
||||
while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
|
||||
/* If whitespace at line start then continuation line */
|
||||
if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME;
|
||||
else state = MIME_START;
|
||||
ntmp = NULL;
|
||||
/* Go through all characters */
|
||||
for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
|
||||
|
||||
/* State machine to handle MIME headers
|
||||
* if this looks horrible that's because it *is*
|
||||
*/
|
||||
|
||||
switch(state) {
|
||||
case MIME_START:
|
||||
if(c == ':') {
|
||||
state = MIME_TYPE;
|
||||
*p = 0;
|
||||
ntmp = strip_ends(q);
|
||||
q = p + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_TYPE:
|
||||
if(c == ';') {
|
||||
mime_debug("Found End Value\n");
|
||||
*p = 0;
|
||||
mhdr = mime_hdr_new(ntmp, strip_ends(q));
|
||||
sk_MIME_HEADER_push(headers, mhdr);
|
||||
ntmp = NULL;
|
||||
q = p + 1;
|
||||
state = MIME_NAME;
|
||||
} else if(c == '(') {
|
||||
save_state = state;
|
||||
state = MIME_COMMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_COMMENT:
|
||||
if(c == ')') {
|
||||
state = save_state;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_NAME:
|
||||
if(c == '=') {
|
||||
state = MIME_VALUE;
|
||||
*p = 0;
|
||||
ntmp = strip_ends(q);
|
||||
q = p + 1;
|
||||
}
|
||||
break ;
|
||||
|
||||
case MIME_VALUE:
|
||||
if(c == ';') {
|
||||
state = MIME_NAME;
|
||||
*p = 0;
|
||||
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
|
||||
ntmp = NULL;
|
||||
q = p + 1;
|
||||
} else if (c == '"') {
|
||||
mime_debug("Found Quote\n");
|
||||
state = MIME_QUOTE;
|
||||
} else if(c == '(') {
|
||||
save_state = state;
|
||||
state = MIME_COMMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIME_QUOTE:
|
||||
if(c == '"') {
|
||||
mime_debug("Found Match Quote\n");
|
||||
state = MIME_VALUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(state == MIME_TYPE) {
|
||||
mhdr = mime_hdr_new(ntmp, strip_ends(q));
|
||||
sk_MIME_HEADER_push(headers, mhdr);
|
||||
} else if(state == MIME_VALUE)
|
||||
mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
|
||||
if(p == linebuf) break; /* Blank line means end of headers */
|
||||
}
|
||||
|
||||
return headers;
|
||||
|
||||
}
|
||||
|
||||
static char *strip_ends(char *name)
|
||||
{
|
||||
return strip_end(strip_start(name));
|
||||
}
|
||||
|
||||
/* Strip a parameter of whitespace from start of param */
|
||||
static char *strip_start(char *name)
|
||||
{
|
||||
char *p, c;
|
||||
/* Look for first non white space or quote */
|
||||
for(p = name; (c = *p) ;p++) {
|
||||
if(c == '"') {
|
||||
/* Next char is start of string if non null */
|
||||
if(p[1]) return p + 1;
|
||||
/* Else null string */
|
||||
return NULL;
|
||||
}
|
||||
if(!isspace((unsigned char)c)) return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* As above but strip from end of string : maybe should handle brackets? */
|
||||
static char *strip_end(char *name)
|
||||
{
|
||||
char *p, c;
|
||||
if(!name) return NULL;
|
||||
/* Look for first non white space or quote */
|
||||
for(p = name + strlen(name) - 1; p >= name ;p--) {
|
||||
c = *p;
|
||||
if(c == '"') {
|
||||
if(p - 1 == name) return NULL;
|
||||
*p = 0;
|
||||
return name;
|
||||
}
|
||||
if(isspace((unsigned char)c)) *p = 0;
|
||||
else return name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MIME_HEADER *mime_hdr_new(char *name, char *value)
|
||||
{
|
||||
MIME_HEADER *mhdr;
|
||||
char *tmpname, *tmpval, *p;
|
||||
int c;
|
||||
if(name) {
|
||||
if(!(tmpname = BUF_strdup(name))) return NULL;
|
||||
for(p = tmpname ; *p; p++) {
|
||||
c = *p;
|
||||
if(isupper(c)) {
|
||||
c = tolower(c);
|
||||
*p = c;
|
||||
}
|
||||
}
|
||||
} else tmpname = NULL;
|
||||
if(value) {
|
||||
if(!(tmpval = BUF_strdup(value))) return NULL;
|
||||
for(p = tmpval ; *p; p++) {
|
||||
c = *p;
|
||||
if(isupper(c)) {
|
||||
c = tolower(c);
|
||||
*p = c;
|
||||
}
|
||||
}
|
||||
} else tmpval = NULL;
|
||||
mhdr = (MIME_HEADER *) OPENSSL_malloc(sizeof(MIME_HEADER));
|
||||
if(!mhdr) return NULL;
|
||||
mhdr->name = tmpname;
|
||||
mhdr->value = tmpval;
|
||||
if(!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) return NULL;
|
||||
return mhdr;
|
||||
}
|
||||
|
||||
static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
|
||||
{
|
||||
char *tmpname, *tmpval, *p;
|
||||
int c;
|
||||
MIME_PARAM *mparam;
|
||||
if(name) {
|
||||
tmpname = BUF_strdup(name);
|
||||
if(!tmpname) return 0;
|
||||
for(p = tmpname ; *p; p++) {
|
||||
c = *p;
|
||||
if(isupper(c)) {
|
||||
c = tolower(c);
|
||||
*p = c;
|
||||
}
|
||||
}
|
||||
} else tmpname = NULL;
|
||||
if(value) {
|
||||
tmpval = BUF_strdup(value);
|
||||
if(!tmpval) return 0;
|
||||
} else tmpval = NULL;
|
||||
/* Parameter values are case sensitive so leave as is */
|
||||
mparam = (MIME_PARAM *) OPENSSL_malloc(sizeof(MIME_PARAM));
|
||||
if(!mparam) return 0;
|
||||
mparam->param_name = tmpname;
|
||||
mparam->param_value = tmpval;
|
||||
sk_MIME_PARAM_push(mhdr->params, mparam);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mime_hdr_cmp(const MIME_HEADER * const *a,
|
||||
const MIME_HEADER * const *b)
|
||||
{
|
||||
return(strcmp((*a)->name, (*b)->name));
|
||||
}
|
||||
|
||||
static int mime_param_cmp(const MIME_PARAM * const *a,
|
||||
const MIME_PARAM * const *b)
|
||||
{
|
||||
return(strcmp((*a)->param_name, (*b)->param_name));
|
||||
}
|
||||
|
||||
/* Find a header with a given name (if possible) */
|
||||
|
||||
static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name)
|
||||
{
|
||||
MIME_HEADER htmp;
|
||||
int idx;
|
||||
htmp.name = name;
|
||||
idx = sk_MIME_HEADER_find(hdrs, &htmp);
|
||||
if(idx < 0) return NULL;
|
||||
return sk_MIME_HEADER_value(hdrs, idx);
|
||||
}
|
||||
|
||||
static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name)
|
||||
{
|
||||
MIME_PARAM param;
|
||||
int idx;
|
||||
param.param_name = name;
|
||||
idx = sk_MIME_PARAM_find(hdr->params, ¶m);
|
||||
if(idx < 0) return NULL;
|
||||
return sk_MIME_PARAM_value(hdr->params, idx);
|
||||
}
|
||||
|
||||
static void mime_hdr_free(MIME_HEADER *hdr)
|
||||
{
|
||||
if(hdr->name) OPENSSL_free(hdr->name);
|
||||
if(hdr->value) OPENSSL_free(hdr->value);
|
||||
if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
|
||||
OPENSSL_free(hdr);
|
||||
}
|
||||
|
||||
static void mime_param_free(MIME_PARAM *param)
|
||||
{
|
||||
if(param->param_name) OPENSSL_free(param->param_name);
|
||||
if(param->param_value) OPENSSL_free(param->param_value);
|
||||
OPENSSL_free(param);
|
||||
}
|
||||
|
||||
/* Check for a multipart boundary. Returns:
|
||||
* 0 : no boundary
|
||||
* 1 : part boundary
|
||||
* 2 : final boundary
|
||||
*/
|
||||
static int mime_bound_check(char *line, int linelen, char *bound, int blen)
|
||||
{
|
||||
if(linelen == -1) linelen = strlen(line);
|
||||
if(blen == -1) blen = strlen(bound);
|
||||
/* Quickly eliminate if line length too short */
|
||||
if(blen + 2 > linelen) return 0;
|
||||
/* Check for part boundary */
|
||||
if(!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) {
|
||||
if(!strncmp(line + blen + 2, "--", 2)) return 2;
|
||||
else return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int strip_eol(char *linebuf, int *plen)
|
||||
{
|
||||
int len = *plen;
|
||||
char *p, c;
|
||||
int is_eol = 0;
|
||||
p = linebuf + len - 1;
|
||||
for (p = linebuf + len - 1; len > 0; len--, p--)
|
||||
{
|
||||
c = *p;
|
||||
if (c == '\n')
|
||||
is_eol = 1;
|
||||
else if (c != '\r')
|
||||
break;
|
||||
}
|
||||
*plen = len;
|
||||
return is_eol;
|
||||
return (PKCS7 *)SMIME_read_asn1(bio, bcont, ASN1_ITEM_rptr(PKCS7));
|
||||
}
|
||||
|
@ -382,6 +382,7 @@ int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si,
|
||||
const unsigned char *md, int mdlen);
|
||||
|
||||
int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
|
||||
ASN1_VALUE *SMIME_read_asn1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
|
||||
PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
|
||||
int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
|
||||
int SMIME_text(BIO *in, BIO *out);
|
||||
|
@ -61,6 +61,9 @@
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rsa.h>
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
#include <openssl/cms.h>
|
||||
#endif
|
||||
#include "asn1_locl.h"
|
||||
|
||||
static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
|
||||
@ -286,6 +289,17 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
V_ASN1_NULL, 0);
|
||||
}
|
||||
return 1;
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
case ASN1_PKEY_CTRL_CMS_SIGN:
|
||||
if (arg1 == 0)
|
||||
{
|
||||
X509_ALGOR *alg;
|
||||
CMS_SignerInfo_get0_algs(arg2, NULL, NULL, NULL, &alg);
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption),
|
||||
V_ASN1_NULL, 0);
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha1;
|
||||
|
@ -435,6 +435,11 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_SIGN:
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
case EVP_PKEY_CTRL_CMS_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_DECRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_SIGN:
|
||||
#endif
|
||||
return 1;
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL,
|
||||
|
@ -480,6 +480,94 @@ STACK_OF(type) \
|
||||
#define sk_BY_DIR_HASH_sort(st) SKM_sk_sort(BY_DIR_HASH, (st))
|
||||
#define sk_BY_DIR_HASH_is_sorted(st) SKM_sk_is_sorted(BY_DIR_HASH, (st))
|
||||
|
||||
#define sk_CMS_CertificateChoices_new(st) SKM_sk_new(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_new_null() SKM_sk_new_null(CMS_CertificateChoices)
|
||||
#define sk_CMS_CertificateChoices_free(st) SKM_sk_free(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_num(st) SKM_sk_num(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_value(st, i) SKM_sk_value(CMS_CertificateChoices, (st), (i))
|
||||
#define sk_CMS_CertificateChoices_set(st, i, val) SKM_sk_set(CMS_CertificateChoices, (st), (i), (val))
|
||||
#define sk_CMS_CertificateChoices_zero(st) SKM_sk_zero(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_push(st, val) SKM_sk_push(CMS_CertificateChoices, (st), (val))
|
||||
#define sk_CMS_CertificateChoices_unshift(st, val) SKM_sk_unshift(CMS_CertificateChoices, (st), (val))
|
||||
#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_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_insert(st, val, i) SKM_sk_insert(CMS_CertificateChoices, (st), (val), (i))
|
||||
#define sk_CMS_CertificateChoices_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_CertificateChoices, (st), (cmp))
|
||||
#define sk_CMS_CertificateChoices_dup(st) SKM_sk_dup(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_shift(st) SKM_sk_shift(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_pop(st) SKM_sk_pop(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_sort(st) SKM_sk_sort(CMS_CertificateChoices, (st))
|
||||
#define sk_CMS_CertificateChoices_is_sorted(st) SKM_sk_is_sorted(CMS_CertificateChoices, (st))
|
||||
|
||||
#define sk_CMS_RecipientInfo_new(st) SKM_sk_new(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_new_null() SKM_sk_new_null(CMS_RecipientInfo)
|
||||
#define sk_CMS_RecipientInfo_free(st) SKM_sk_free(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_num(st) SKM_sk_num(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_value(st, i) SKM_sk_value(CMS_RecipientInfo, (st), (i))
|
||||
#define sk_CMS_RecipientInfo_set(st, i, val) SKM_sk_set(CMS_RecipientInfo, (st), (i), (val))
|
||||
#define sk_CMS_RecipientInfo_zero(st) SKM_sk_zero(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_push(st, val) SKM_sk_push(CMS_RecipientInfo, (st), (val))
|
||||
#define sk_CMS_RecipientInfo_unshift(st, val) SKM_sk_unshift(CMS_RecipientInfo, (st), (val))
|
||||
#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_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_insert(st, val, i) SKM_sk_insert(CMS_RecipientInfo, (st), (val), (i))
|
||||
#define sk_CMS_RecipientInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientInfo, (st), (cmp))
|
||||
#define sk_CMS_RecipientInfo_dup(st) SKM_sk_dup(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_shift(st) SKM_sk_shift(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_pop(st) SKM_sk_pop(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_sort(st) SKM_sk_sort(CMS_RecipientInfo, (st))
|
||||
#define sk_CMS_RecipientInfo_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientInfo, (st))
|
||||
|
||||
#define sk_CMS_RevocationInfoChoice_new(st) SKM_sk_new(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_new_null() SKM_sk_new_null(CMS_RevocationInfoChoice)
|
||||
#define sk_CMS_RevocationInfoChoice_free(st) SKM_sk_free(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_num(st) SKM_sk_num(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_value(st, i) SKM_sk_value(CMS_RevocationInfoChoice, (st), (i))
|
||||
#define sk_CMS_RevocationInfoChoice_set(st, i, val) SKM_sk_set(CMS_RevocationInfoChoice, (st), (i), (val))
|
||||
#define sk_CMS_RevocationInfoChoice_zero(st) SKM_sk_zero(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_push(st, val) SKM_sk_push(CMS_RevocationInfoChoice, (st), (val))
|
||||
#define sk_CMS_RevocationInfoChoice_unshift(st, val) SKM_sk_unshift(CMS_RevocationInfoChoice, (st), (val))
|
||||
#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_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_insert(st, val, i) SKM_sk_insert(CMS_RevocationInfoChoice, (st), (val), (i))
|
||||
#define sk_CMS_RevocationInfoChoice_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RevocationInfoChoice, (st), (cmp))
|
||||
#define sk_CMS_RevocationInfoChoice_dup(st) SKM_sk_dup(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_shift(st) SKM_sk_shift(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_pop(st) SKM_sk_pop(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_sort(st) SKM_sk_sort(CMS_RevocationInfoChoice, (st))
|
||||
#define sk_CMS_RevocationInfoChoice_is_sorted(st) SKM_sk_is_sorted(CMS_RevocationInfoChoice, (st))
|
||||
|
||||
#define sk_CMS_SignerInfo_new(st) SKM_sk_new(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_new_null() SKM_sk_new_null(CMS_SignerInfo)
|
||||
#define sk_CMS_SignerInfo_free(st) SKM_sk_free(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_num(st) SKM_sk_num(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_value(st, i) SKM_sk_value(CMS_SignerInfo, (st), (i))
|
||||
#define sk_CMS_SignerInfo_set(st, i, val) SKM_sk_set(CMS_SignerInfo, (st), (i), (val))
|
||||
#define sk_CMS_SignerInfo_zero(st) SKM_sk_zero(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_push(st, val) SKM_sk_push(CMS_SignerInfo, (st), (val))
|
||||
#define sk_CMS_SignerInfo_unshift(st, val) SKM_sk_unshift(CMS_SignerInfo, (st), (val))
|
||||
#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_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_insert(st, val, i) SKM_sk_insert(CMS_SignerInfo, (st), (val), (i))
|
||||
#define sk_CMS_SignerInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_SignerInfo, (st), (cmp))
|
||||
#define sk_CMS_SignerInfo_dup(st) SKM_sk_dup(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_shift(st) SKM_sk_shift(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_pop(st) SKM_sk_pop(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_sort(st) SKM_sk_sort(CMS_SignerInfo, (st))
|
||||
#define sk_CMS_SignerInfo_is_sorted(st) SKM_sk_is_sorted(CMS_SignerInfo, (st))
|
||||
|
||||
#define sk_CONF_IMODULE_new(st) SKM_sk_new(CONF_IMODULE, (st))
|
||||
#define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE)
|
||||
#define sk_CONF_IMODULE_free(st) SKM_sk_free(CONF_IMODULE, (st))
|
||||
|
@ -146,9 +146,10 @@ struct X509_algor_st
|
||||
ASN1_TYPE *parameter;
|
||||
} /* X509_ALGOR */;
|
||||
|
||||
DECLARE_STACK_OF(X509_ALGOR)
|
||||
DECLARE_ASN1_SET_OF(X509_ALGOR)
|
||||
|
||||
typedef STACK_OF(X509_ALGOR) X509_ALGORS;
|
||||
|
||||
typedef struct X509_val_st
|
||||
{
|
||||
ASN1_TIME *notBefore;
|
||||
@ -768,6 +769,7 @@ X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
|
||||
X509 * X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey);
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
|
||||
DECLARE_ASN1_FUNCTIONS(X509_VAL)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
|
||||
@ -1125,7 +1127,11 @@ DECLARE_ASN1_FUNCTIONS(PBEPARAM)
|
||||
DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
|
||||
DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
|
||||
|
||||
X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, int saltlen);
|
||||
int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
|
||||
const unsigned char *salt, int saltlen);
|
||||
|
||||
X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
|
||||
const unsigned char *salt, int saltlen);
|
||||
X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
|
||||
unsigned char *salt, int saltlen);
|
||||
X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
|
||||
|
@ -67,8 +67,7 @@
|
||||
|
||||
int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
|
||||
{
|
||||
if (!x) return 0;
|
||||
return(sk_X509_ATTRIBUTE_num(x));
|
||||
return sk_X509_ATTRIBUTE_num(x);
|
||||
}
|
||||
|
||||
int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
|
||||
|
134
ssl/Makefile
134
ssl/Makefile
@ -142,26 +142,25 @@ d1_both.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
d1_both.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
d1_both.o: ../include/openssl/x509_vfy.h d1_both.c ssl_locl.h
|
||||
d1_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
|
||||
d1_clnt.o: ../include/openssl/bn.h ../include/openssl/buffer.h
|
||||
d1_clnt.o: ../include/openssl/comp.h ../include/openssl/crypto.h
|
||||
d1_clnt.o: ../include/openssl/dh.h ../include/openssl/dsa.h
|
||||
d1_clnt.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
|
||||
d1_clnt.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
|
||||
d1_clnt.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
|
||||
d1_clnt.o: ../include/openssl/evp.h ../include/openssl/kssl.h
|
||||
d1_clnt.o: ../include/openssl/lhash.h ../include/openssl/md5.h
|
||||
d1_clnt.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
|
||||
d1_clnt.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
|
||||
d1_clnt.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
|
||||
d1_clnt.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
|
||||
d1_clnt.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
|
||||
d1_clnt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
|
||||
d1_clnt.o: ../include/openssl/sha.h ../include/openssl/ssl.h
|
||||
d1_clnt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
|
||||
d1_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
|
||||
d1_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
|
||||
d1_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_clnt.c
|
||||
d1_clnt.o: ssl_locl.h
|
||||
d1_clnt.o: ../include/openssl/buffer.h ../include/openssl/comp.h
|
||||
d1_clnt.o: ../include/openssl/crypto.h ../include/openssl/dh.h
|
||||
d1_clnt.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
|
||||
d1_clnt.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
|
||||
d1_clnt.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
|
||||
d1_clnt.o: ../include/openssl/err.h ../include/openssl/evp.h
|
||||
d1_clnt.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
|
||||
d1_clnt.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
|
||||
d1_clnt.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
|
||||
d1_clnt.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
|
||||
d1_clnt.o: ../include/openssl/pem.h ../include/openssl/pem2.h
|
||||
d1_clnt.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
|
||||
d1_clnt.o: ../include/openssl/rand.h ../include/openssl/rsa.h
|
||||
d1_clnt.o: ../include/openssl/safestack.h ../include/openssl/sha.h
|
||||
d1_clnt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
|
||||
d1_clnt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
|
||||
d1_clnt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
d1_clnt.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
d1_clnt.o: ../include/openssl/x509_vfy.h d1_clnt.c ssl_locl.h
|
||||
d1_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
|
||||
d1_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h
|
||||
d1_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
|
||||
@ -232,34 +231,33 @@ d1_pkt.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
|
||||
d1_pkt.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
|
||||
d1_pkt.o: ../include/openssl/pem.h ../include/openssl/pem2.h
|
||||
d1_pkt.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
|
||||
d1_pkt.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
|
||||
d1_pkt.o: ../include/openssl/sha.h ../include/openssl/ssl.h
|
||||
d1_pkt.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
|
||||
d1_pkt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
|
||||
d1_pkt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
|
||||
d1_pkt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_pkt.c
|
||||
d1_pkt.o: ssl_locl.h
|
||||
d1_pkt.o: ../include/openssl/rand.h ../include/openssl/rsa.h
|
||||
d1_pkt.o: ../include/openssl/safestack.h ../include/openssl/sha.h
|
||||
d1_pkt.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
|
||||
d1_pkt.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
|
||||
d1_pkt.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
d1_pkt.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
d1_pkt.o: ../include/openssl/x509_vfy.h d1_pkt.c ssl_locl.h
|
||||
d1_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
|
||||
d1_srvr.o: ../include/openssl/bn.h ../include/openssl/buffer.h
|
||||
d1_srvr.o: ../include/openssl/comp.h ../include/openssl/crypto.h
|
||||
d1_srvr.o: ../include/openssl/dh.h ../include/openssl/dsa.h
|
||||
d1_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
|
||||
d1_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
|
||||
d1_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
|
||||
d1_srvr.o: ../include/openssl/evp.h ../include/openssl/kssl.h
|
||||
d1_srvr.o: ../include/openssl/lhash.h ../include/openssl/md5.h
|
||||
d1_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
|
||||
d1_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
|
||||
d1_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
|
||||
d1_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
|
||||
d1_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
|
||||
d1_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
|
||||
d1_srvr.o: ../include/openssl/sha.h ../include/openssl/ssl.h
|
||||
d1_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
|
||||
d1_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
|
||||
d1_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
|
||||
d1_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_srvr.c
|
||||
d1_srvr.o: ssl_locl.h
|
||||
d1_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h
|
||||
d1_srvr.o: ../include/openssl/crypto.h ../include/openssl/dh.h
|
||||
d1_srvr.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
|
||||
d1_srvr.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
|
||||
d1_srvr.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
|
||||
d1_srvr.o: ../include/openssl/err.h ../include/openssl/evp.h
|
||||
d1_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
|
||||
d1_srvr.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
|
||||
d1_srvr.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
|
||||
d1_srvr.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
|
||||
d1_srvr.o: ../include/openssl/pem.h ../include/openssl/pem2.h
|
||||
d1_srvr.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
|
||||
d1_srvr.o: ../include/openssl/rand.h ../include/openssl/rsa.h
|
||||
d1_srvr.o: ../include/openssl/safestack.h ../include/openssl/sha.h
|
||||
d1_srvr.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
|
||||
d1_srvr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
|
||||
d1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
d1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
d1_srvr.o: ../include/openssl/x509_vfy.h d1_srvr.c ssl_locl.h
|
||||
kssl.o: ../include/openssl/asn1.h ../include/openssl/bio.h
|
||||
kssl.o: ../include/openssl/buffer.h ../include/openssl/comp.h
|
||||
kssl.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
|
||||
@ -747,18 +745,18 @@ ssl_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
|
||||
ssl_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
|
||||
ssl_lib.o: ../include/openssl/evp.h ../include/openssl/kssl.h
|
||||
ssl_lib.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
|
||||
ssl_lib.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
|
||||
ssl_lib.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
|
||||
ssl_lib.o: ../include/openssl/pem.h ../include/openssl/pem2.h
|
||||
ssl_lib.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
|
||||
ssl_lib.o: ../include/openssl/rand.h ../include/openssl/rsa.h
|
||||
ssl_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h
|
||||
ssl_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
|
||||
ssl_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
|
||||
ssl_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
ssl_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
ssl_lib.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h kssl_lcl.h
|
||||
ssl_lib.o: ssl_lib.c ssl_locl.h
|
||||
ssl_lib.o: ../include/openssl/objects.h ../include/openssl/ocsp.h
|
||||
ssl_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
|
||||
ssl_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
|
||||
ssl_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
|
||||
ssl_lib.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
|
||||
ssl_lib.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
|
||||
ssl_lib.o: ../include/openssl/sha.h ../include/openssl/ssl.h
|
||||
ssl_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
|
||||
ssl_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
|
||||
ssl_lib.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
|
||||
ssl_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
|
||||
ssl_lib.o: ../include/openssl/x509v3.h kssl_lcl.h ssl_lib.c ssl_locl.h
|
||||
ssl_rsa.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
|
||||
ssl_rsa.o: ../include/openssl/buffer.h ../include/openssl/comp.h
|
||||
ssl_rsa.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
|
||||
@ -876,13 +874,14 @@ t1_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h
|
||||
t1_enc.o: t1_enc.c
|
||||
t1_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
|
||||
t1_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h
|
||||
t1_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
|
||||
t1_lib.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
|
||||
t1_lib.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
|
||||
t1_lib.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
|
||||
t1_lib.o: ../include/openssl/evp.h ../include/openssl/hmac.h
|
||||
t1_lib.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
|
||||
t1_lib.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
|
||||
t1_lib.o: ../include/openssl/conf.h ../include/openssl/crypto.h
|
||||
t1_lib.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
|
||||
t1_lib.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
|
||||
t1_lib.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
|
||||
t1_lib.o: ../include/openssl/err.h ../include/openssl/evp.h
|
||||
t1_lib.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
|
||||
t1_lib.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
|
||||
t1_lib.o: ../include/openssl/objects.h ../include/openssl/ocsp.h
|
||||
t1_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
|
||||
t1_lib.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
|
||||
t1_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
|
||||
@ -892,7 +891,8 @@ t1_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
|
||||
t1_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
|
||||
t1_lib.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
|
||||
t1_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
|
||||
t1_lib.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_lib.c
|
||||
t1_lib.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h ssl_locl.h
|
||||
t1_lib.o: t1_lib.c
|
||||
t1_meth.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
|
||||
t1_meth.o: ../include/openssl/buffer.h ../include/openssl/comp.h
|
||||
t1_meth.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
|
||||
|
@ -79,7 +79,7 @@ my $OS2=0;
|
||||
my $safe_stack_def = 0;
|
||||
|
||||
my @known_platforms = ( "__FreeBSD__", "PERL5", "NeXT",
|
||||
"EXPORT_VAR_AS_FUNCTION" );
|
||||
"EXPORT_VAR_AS_FUNCTION", "ZLIB" );
|
||||
my @known_ossl_platforms = ( "VMS", "WIN16", "WIN32", "WINNT", "OS2" );
|
||||
my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
|
||||
"CAST", "MD2", "MD4", "MD5", "SHA", "SHA0", "SHA1",
|
||||
@ -99,6 +99,8 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
|
||||
"RFC3779",
|
||||
# TLS
|
||||
"TLSEXT", "PSK",
|
||||
# CMS
|
||||
"CMS",
|
||||
# Deprecated functions
|
||||
"DEPRECATED" );
|
||||
|
||||
@ -118,7 +120,9 @@ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
|
||||
my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5;
|
||||
my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw;
|
||||
my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
|
||||
my $no_rfc3779; my $no_psk; my $no_tlsext;
|
||||
my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms;
|
||||
|
||||
my $zlib;
|
||||
|
||||
|
||||
foreach (@ARGV, split(/ /, $options))
|
||||
@ -140,6 +144,11 @@ foreach (@ARGV, split(/ /, $options))
|
||||
}
|
||||
$VMS=1 if $_ eq "VMS";
|
||||
$OS2=1 if $_ eq "OS2";
|
||||
if ($_ eq "zlib" || $_ eq "zlib-dynamic"
|
||||
|| $_ eq "enable-zlib-dynamic") {
|
||||
$zlib = 1;
|
||||
}
|
||||
|
||||
|
||||
$do_ssl=1 if $_ eq "ssleay";
|
||||
if ($_ eq "ssl") {
|
||||
@ -199,6 +208,7 @@ foreach (@ARGV, split(/ /, $options))
|
||||
elsif (/^no-gmp$/) { $no_gmp=1; }
|
||||
elsif (/^no-rfc3779$/) { $no_rfc3779=1; }
|
||||
elsif (/^no-tlsext$/) { $no_tlsext=1; }
|
||||
elsif (/^no-cms$/) { $no_cms=1; }
|
||||
}
|
||||
|
||||
|
||||
@ -295,6 +305,7 @@ $crypto.=" crypto/ui/ui.h crypto/ui/ui_compat.h";
|
||||
$crypto.=" crypto/krb5/krb5_asn.h";
|
||||
$crypto.=" crypto/store/store.h";
|
||||
$crypto.=" crypto/pqueue/pqueue.h";
|
||||
$crypto.=" crypto/cms/cms.h";
|
||||
|
||||
my $symhacks="crypto/symhacks.h";
|
||||
|
||||
@ -1080,6 +1091,7 @@ sub is_valid
|
||||
if ($keyword eq "EXPORT_VAR_AS_FUNCTION" && ($VMSVAX || $W32 || $W16)) {
|
||||
return 1;
|
||||
}
|
||||
if ($keyword eq "ZLIB" && $zlib) { return 1; }
|
||||
return 0;
|
||||
} else {
|
||||
# algorithms
|
||||
@ -1124,6 +1136,7 @@ sub is_valid
|
||||
if ($keyword eq "RFC3779" && $no_rfc3779) { return 0; }
|
||||
if ($keyword eq "TLSEXT" && $no_tlsext) { return 0; }
|
||||
if ($keyword eq "PSK" && $no_psk) { return 0; }
|
||||
if ($keyword eq "CMS" && $no_cms) { return 0; }
|
||||
if ($keyword eq "DEPRECATED" && $no_deprecated) { return 0; }
|
||||
|
||||
# Nothing recognise as true
|
||||
|
Loading…
Reference in New Issue
Block a user