os/ossrv/ssl/libcrypto/src/crypto/pkcs12/p12_kiss.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/pkcs12/p12_kiss.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,297 @@
     1.4 +/* p12_kiss.c */
     1.5 +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
     1.6 + * project 1999.
     1.7 + */
     1.8 +/* ====================================================================
     1.9 + * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
    1.10 + *
    1.11 + * Redistribution and use in source and binary forms, with or without
    1.12 + * modification, are permitted provided that the following conditions
    1.13 + * are met:
    1.14 + *
    1.15 + * 1. Redistributions of source code must retain the above copyright
    1.16 + *    notice, this list of conditions and the following disclaimer. 
    1.17 + *
    1.18 + * 2. Redistributions in binary form must reproduce the above copyright
    1.19 + *    notice, this list of conditions and the following disclaimer in
    1.20 + *    the documentation and/or other materials provided with the
    1.21 + *    distribution.
    1.22 + *
    1.23 + * 3. All advertising materials mentioning features or use of this
    1.24 + *    software must display the following acknowledgment:
    1.25 + *    "This product includes software developed by the OpenSSL Project
    1.26 + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
    1.27 + *
    1.28 + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
    1.29 + *    endorse or promote products derived from this software without
    1.30 + *    prior written permission. For written permission, please contact
    1.31 + *    licensing@OpenSSL.org.
    1.32 + *
    1.33 + * 5. Products derived from this software may not be called "OpenSSL"
    1.34 + *    nor may "OpenSSL" appear in their names without prior written
    1.35 + *    permission of the OpenSSL Project.
    1.36 + *
    1.37 + * 6. Redistributions of any form whatsoever must retain the following
    1.38 + *    acknowledgment:
    1.39 + *    "This product includes software developed by the OpenSSL Project
    1.40 + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
    1.41 + *
    1.42 + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
    1.43 + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.44 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    1.45 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
    1.46 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.47 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    1.48 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    1.49 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.50 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    1.51 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.52 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    1.53 + * OF THE POSSIBILITY OF SUCH DAMAGE.
    1.54 + * ====================================================================
    1.55 + *
    1.56 + * This product includes cryptographic software written by Eric Young
    1.57 + * (eay@cryptsoft.com).  This product includes software written by Tim
    1.58 + * Hudson (tjh@cryptsoft.com).
    1.59 + *
    1.60 + */
    1.61 +
    1.62 +#include <stdio.h>
    1.63 +#include "cryptlib.h"
    1.64 +#include <openssl/pkcs12.h>
    1.65 +
    1.66 +/* Simplified PKCS#12 routines */
    1.67 +
    1.68 +static int parse_pk12( PKCS12 *p12, const char *pass, int passlen,
    1.69 +		EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca);
    1.70 +
    1.71 +static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
    1.72 +		       int passlen, EVP_PKEY **pkey, X509 **cert,
    1.73 +		       STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid,
    1.74 +		       char *keymatch);
    1.75 +
    1.76 +static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen,
    1.77 +			EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca,
    1.78 +			ASN1_OCTET_STRING **keyid, char *keymatch);
    1.79 +
    1.80 +/* Parse and decrypt a PKCS#12 structure returning user key, user cert
    1.81 + * and other (CA) certs. Note either ca should be NULL, *ca should be NULL,
    1.82 + * or it should point to a valid STACK structure. pkey and cert can be
    1.83 + * passed unitialised.
    1.84 + */
    1.85 +
    1.86 +EXPORT_C int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
    1.87 +	     STACK_OF(X509) **ca)
    1.88 +{
    1.89 +
    1.90 +	/* Check for NULL PKCS12 structure */
    1.91 +
    1.92 +	if(!p12) {
    1.93 +		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER);
    1.94 +		return 0;
    1.95 +	}
    1.96 +
    1.97 +	/* Allocate stack for ca certificates if needed */
    1.98 +	if ((ca != NULL) && (*ca == NULL)) {
    1.99 +		if (!(*ca = sk_X509_new_null())) {
   1.100 +			PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE);
   1.101 +			return 0;
   1.102 +		}
   1.103 +	}
   1.104 +
   1.105 +	if(pkey) *pkey = NULL;
   1.106 +	if(cert) *cert = NULL;
   1.107 +
   1.108 +	/* Check the mac */
   1.109 +
   1.110 +	/* If password is zero length or NULL then try verifying both cases
   1.111 +	 * to determine which password is correct. The reason for this is that
   1.112 +	 * under PKCS#12 password based encryption no password and a zero length
   1.113 +	 * password are two different things...
   1.114 +	 */
   1.115 +
   1.116 +	if(!pass || !*pass) {
   1.117 +		if(PKCS12_verify_mac(p12, NULL, 0)) pass = NULL;
   1.118 +		else if(PKCS12_verify_mac(p12, "", 0)) pass = "";
   1.119 +		else {
   1.120 +			PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
   1.121 +			goto err;
   1.122 +		}
   1.123 +	} else if (!PKCS12_verify_mac(p12, pass, -1)) {
   1.124 +		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
   1.125 +		goto err;
   1.126 +	}
   1.127 +
   1.128 +	if (!parse_pk12 (p12, pass, -1, pkey, cert, ca))
   1.129 +		{
   1.130 +		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR);
   1.131 +		goto err;
   1.132 +		}
   1.133 +
   1.134 +	return 1;
   1.135 +
   1.136 + err:
   1.137 +
   1.138 +	if (pkey && *pkey) EVP_PKEY_free(*pkey);
   1.139 +	if (cert && *cert) X509_free(*cert);
   1.140 +	if (ca) sk_X509_pop_free(*ca, X509_free);
   1.141 +	return 0;
   1.142 +
   1.143 +}
   1.144 +
   1.145 +/* Parse the outer PKCS#12 structure */
   1.146 +
   1.147 +static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
   1.148 +	     EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
   1.149 +{
   1.150 +	STACK_OF(PKCS7) *asafes;
   1.151 +	STACK_OF(PKCS12_SAFEBAG) *bags;
   1.152 +	int i, bagnid;
   1.153 +	PKCS7 *p7;
   1.154 +	ASN1_OCTET_STRING *keyid = NULL;
   1.155 +
   1.156 +	char keymatch = 0;
   1.157 +	if (!(asafes = PKCS12_unpack_authsafes (p12))) return 0;
   1.158 +	for (i = 0; i < sk_PKCS7_num (asafes); i++) {
   1.159 +		p7 = sk_PKCS7_value (asafes, i);
   1.160 +		bagnid = OBJ_obj2nid (p7->type);
   1.161 +		if (bagnid == NID_pkcs7_data) {
   1.162 +			bags = PKCS12_unpack_p7data(p7);
   1.163 +		} else if (bagnid == NID_pkcs7_encrypted) {
   1.164 +			bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
   1.165 +		} else continue;
   1.166 +		if (!bags) {
   1.167 +			sk_PKCS7_pop_free(asafes, PKCS7_free);
   1.168 +			return 0;
   1.169 +		}
   1.170 +	    	if (!parse_bags(bags, pass, passlen, pkey, cert, ca,
   1.171 +							 &keyid, &keymatch)) {
   1.172 +			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
   1.173 +			sk_PKCS7_pop_free(asafes, PKCS7_free);
   1.174 +			return 0;
   1.175 +		}
   1.176 +		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
   1.177 +	}
   1.178 +	sk_PKCS7_pop_free(asafes, PKCS7_free);
   1.179 +	if (keyid) M_ASN1_OCTET_STRING_free(keyid);
   1.180 +	return 1;
   1.181 +}
   1.182 +
   1.183 +
   1.184 +static int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
   1.185 +		      int passlen, EVP_PKEY **pkey, X509 **cert,
   1.186 +		      STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid,
   1.187 +		      char *keymatch)
   1.188 +{
   1.189 +	int i;
   1.190 +	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
   1.191 +		if (!parse_bag(sk_PKCS12_SAFEBAG_value (bags, i),
   1.192 +			 pass, passlen, pkey, cert, ca, keyid,
   1.193 +							 keymatch)) return 0;
   1.194 +	}
   1.195 +	return 1;
   1.196 +}
   1.197 +
   1.198 +#define MATCH_KEY  0x1
   1.199 +#define MATCH_CERT 0x2
   1.200 +#define MATCH_ALL  0x3
   1.201 +
   1.202 +static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
   1.203 +		     EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca,
   1.204 +		     ASN1_OCTET_STRING **keyid,
   1.205 +		     char *keymatch)
   1.206 +{
   1.207 +	PKCS8_PRIV_KEY_INFO *p8;
   1.208 +	X509 *x509;
   1.209 +	ASN1_OCTET_STRING *lkey = NULL, *ckid = NULL;
   1.210 +	ASN1_TYPE *attrib;
   1.211 +	ASN1_BMPSTRING *fname = NULL;
   1.212 +
   1.213 +	if ((attrib = PKCS12_get_attr (bag, NID_friendlyName)))
   1.214 +		fname = attrib->value.bmpstring;
   1.215 +
   1.216 +	if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) {
   1.217 +		lkey = attrib->value.octet_string;
   1.218 +		ckid = lkey;
   1.219 +	}
   1.220 +
   1.221 +	/* Check for any local key id matching (if needed) */
   1.222 +	if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) {
   1.223 +		if (*keyid) {
   1.224 +			if (M_ASN1_OCTET_STRING_cmp(*keyid, lkey)) lkey = NULL;
   1.225 +		} else {
   1.226 +			if (!(*keyid = M_ASN1_OCTET_STRING_dup(lkey))) {
   1.227 +				PKCS12err(PKCS12_F_PARSE_BAG,ERR_R_MALLOC_FAILURE);
   1.228 +				return 0;
   1.229 +		    }
   1.230 +		}
   1.231 +	}
   1.232 +	
   1.233 +	switch (M_PKCS12_bag_type(bag))
   1.234 +	{
   1.235 +	case NID_keyBag:
   1.236 +		if (!lkey || !pkey) return 1;	
   1.237 +		if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag))) return 0;
   1.238 +		*keymatch |= MATCH_KEY;
   1.239 +	break;
   1.240 +
   1.241 +	case NID_pkcs8ShroudedKeyBag:
   1.242 +		if (!lkey || !pkey) return 1;	
   1.243 +		if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
   1.244 +				return 0;
   1.245 +		*pkey = EVP_PKCS82PKEY(p8);
   1.246 +		PKCS8_PRIV_KEY_INFO_free(p8);
   1.247 +		if (!(*pkey)) return 0;
   1.248 +		*keymatch |= MATCH_KEY;
   1.249 +	break;
   1.250 +
   1.251 +	case NID_certBag:
   1.252 +		if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
   1.253 +								 return 1;
   1.254 +		if (!(x509 = PKCS12_certbag2x509(bag))) return 0;
   1.255 +		if(ckid)
   1.256 +			{
   1.257 +			if (!X509_keyid_set1(x509, ckid->data, ckid->length))
   1.258 +				{
   1.259 +				X509_free(x509);
   1.260 +				return 0;
   1.261 +				}
   1.262 +			}
   1.263 +		if(fname) {
   1.264 +			int len, r;
   1.265 +			unsigned char *data;
   1.266 +			len = ASN1_STRING_to_UTF8(&data, fname);
   1.267 +			if(len > 0) {
   1.268 +				r = X509_alias_set1(x509, data, len);
   1.269 +				OPENSSL_free(data);
   1.270 +				if (!r)
   1.271 +					{
   1.272 +					X509_free(x509);
   1.273 +					return 0;
   1.274 +					}
   1.275 +			}
   1.276 +		}
   1.277 +
   1.278 +
   1.279 +		if (lkey) {
   1.280 +			*keymatch |= MATCH_CERT;
   1.281 +			if (cert) *cert = x509;
   1.282 +			else X509_free(x509);
   1.283 +		} else {
   1.284 +			if(ca) sk_X509_push (*ca, x509);
   1.285 +			else X509_free(x509);
   1.286 +		}
   1.287 +	break;
   1.288 +
   1.289 +	case NID_safeContentsBag:
   1.290 +		return parse_bags(bag->value.safes, pass, passlen,
   1.291 +			 		pkey, cert, ca, keyid, keymatch);
   1.292 +	break;
   1.293 +
   1.294 +	default:
   1.295 +		return 1;
   1.296 +	break;
   1.297 +	}
   1.298 +	return 1;
   1.299 +}
   1.300 +