Socket-Class

 view release on metacpan or  search on metacpan

xs/sc_ssl/openssl/source/crypto/pkcs12/p12_kiss.c  view on Meta::CPAN


	if(pkey) *pkey = NULL;
	if(cert) *cert = NULL;

	/* Check the mac */

	/* If password is zero length or NULL then try verifying both cases
	 * to determine which password is correct. The reason for this is that
	 * under PKCS#12 password based encryption no password and a zero length
	 * password are two different things...
	 */

	if(!pass || !*pass) {
		if(PKCS12_verify_mac(p12, NULL, 0)) pass = NULL;
		else if(PKCS12_verify_mac(p12, "", 0)) pass = "";
		else {
			PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
			goto err;
		}
	} else if (!PKCS12_verify_mac(p12, pass, -1)) {
		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
		goto err;
	}

	if (!parse_pk12 (p12, pass, -1, pkey, cert, ca))
		{
		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR);
		goto err;
		}

	return 1;

 err:

	if (pkey && *pkey) EVP_PKEY_free(*pkey);
	if (cert && *cert) X509_free(*cert);
	if (ca) sk_X509_pop_free(*ca, X509_free);
	return 0;

}

/* Parse the outer PKCS#12 structure */

static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
	     EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
{
	STACK_OF(PKCS7) *asafes;
	STACK_OF(PKCS12_SAFEBAG) *bags;
	int i, bagnid;
	PKCS7 *p7;
	ASN1_OCTET_STRING *keyid = NULL;

	char keymatch = 0;
	if (!(asafes = PKCS12_unpack_authsafes (p12))) return 0;
	for (i = 0; i < sk_PKCS7_num (asafes); i++) {
		p7 = sk_PKCS7_value (asafes, i);
		bagnid = OBJ_obj2nid (p7->type);
		if (bagnid == NID_pkcs7_data) {
			bags = PKCS12_unpack_p7data(p7);
		} else if (bagnid == NID_pkcs7_encrypted) {
			bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
		} else continue;
		if (!bags) {
			sk_PKCS7_pop_free(asafes, PKCS7_free);
			return 0;
		}
	    	if (!parse_bags(bags, pass, passlen, pkey, cert, ca,
							 &keyid, &keymatch)) {
			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
			sk_PKCS7_pop_free(asafes, PKCS7_free);
			return 0;
		}
		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
	}
	sk_PKCS7_pop_free(asafes, PKCS7_free);
	if (keyid) M_ASN1_OCTET_STRING_free(keyid);
	return 1;
}


static int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
		      int passlen, EVP_PKEY **pkey, X509 **cert,
		      STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid,
		      char *keymatch)
{
	int i;
	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
		if (!parse_bag(sk_PKCS12_SAFEBAG_value (bags, i),
			 pass, passlen, pkey, cert, ca, keyid,
							 keymatch)) return 0;
	}
	return 1;
}

#define MATCH_KEY  0x1
#define MATCH_CERT 0x2
#define MATCH_ALL  0x3

static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
		     EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca,
		     ASN1_OCTET_STRING **keyid,
		     char *keymatch)
{
	PKCS8_PRIV_KEY_INFO *p8;
	X509 *x509;
	ASN1_OCTET_STRING *lkey = NULL, *ckid = NULL;
	ASN1_TYPE *attrib;
	ASN1_BMPSTRING *fname = NULL;

	if ((attrib = PKCS12_get_attr (bag, NID_friendlyName)))
		fname = attrib->value.bmpstring;

	if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) {
		lkey = attrib->value.octet_string;
		ckid = lkey;
	}

	/* Check for any local key id matching (if needed) */
	if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) {
		if (*keyid) {
			if (M_ASN1_OCTET_STRING_cmp(*keyid, lkey)) lkey = NULL;



( run in 0.711 second using v1.01-cache-2.11-cpan-63c85eba8c4 )