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 +