p12exp.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,408 行 · 第 1/3 页

C
1,408
字号
    int i, j;    SECComparison rv = SECEqual;    SECItem *t_name;    SEC_PKCS12BaggageItem *bag;    if((luggage == NULL) || (name == NULL)) {	return NULL;    }    i = 0;    while((found == PR_FALSE) && (i < luggage->luggage_size)) {	j = 0;	bag = luggage->bags[i];	while((found == PR_FALSE) && (j < bag->nEspvks)) {	    espvk = bag->espvks[j];	    if(espvk->poolp == NULL) {		espvk->poolp = luggage->poolp;	    }	    t_name = SECITEM_DupItem(&espvk->espvkData.nickname);	    if(t_name != NULL) {		rv = SECITEM_CompareItem(name, t_name);		if(rv == SECEqual) {		    found = PR_TRUE;		}		SECITEM_FreeItem(t_name, PR_TRUE);	    } else {		PORT_SetError(SEC_ERROR_NO_MEMORY);		return NULL;	    }	    j++;	}	i++;    }    if(found != PR_TRUE) {	PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME);	return NULL;    }    return espvk;}/* locates a certificate and copies the thumbprint to the * appropriate private key */static SECStatus sec_pkcs12_propagate_thumbprints(SECItem **nicknames,				 CERTCertificate **ref_certs,				 SEC_PKCS12SafeContents *safe,				 SEC_PKCS12Baggage *baggage){    SEC_PKCS12CertAndCRL *cert;    SEC_PKCS12PrivateKey *key;    SEC_PKCS12ESPVKItem *espvk;    int i;    PRBool error = PR_FALSE;    SECStatus rv = SECFailure;    if((nicknames == NULL) || (safe == NULL)) {	return SECFailure;    }    i = 0;    while((nicknames[i] != NULL) && (error == PR_FALSE)) {	/* process all certs */	cert = (SEC_PKCS12CertAndCRL *)sec_pkcs12_find_object(safe, baggage,					SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID,					nicknames[i], NULL);	if(cert != NULL) {	    /* locate key and copy thumbprint */	    key = (SEC_PKCS12PrivateKey *)sec_pkcs12_find_object(safe, baggage,	    				SEC_OID_PKCS12_KEY_BAG_ID,	    				nicknames[i], NULL);	    if(key != NULL) {		key->pvkData.poolp = key->poolp;		rv = sec_pkcs12_add_thumbprint(&key->pvkData, 			&cert->value.x509->thumbprint);		if(rv == SECFailure)		    error = PR_TRUE;  /* XXX Set error? */	    }	    /* look in the baggage as well...*/	    if((baggage != NULL) && (error == PR_FALSE)) {		espvk = sec_pkcs12_get_espvk_by_name(baggage, nicknames[i]);		if(espvk != NULL) {		    espvk->espvkData.poolp = espvk->poolp;		    rv = sec_pkcs12_add_thumbprint(&espvk->espvkData,			&cert->value.x509->thumbprint);		    if(rv == SECFailure)			error = PR_TRUE;  /* XXX Set error? */		}	    }	}	i++;    }    if(error == PR_TRUE) {	return SECFailure;    }    return SECSuccess;}/* append a safe bag to the end of the safe contents list */SECStatus sec_pkcs12_append_safe_bag(SEC_PKCS12SafeContents *safe,			   SEC_PKCS12SafeBag *bag){    int size;    void *mark = NULL, *dummy = NULL;    if((bag == NULL) || (safe == NULL))	return SECFailure;    mark = PORT_ArenaMark(safe->poolp);    size = (safe->safe_size * sizeof(SEC_PKCS12SafeBag *));        if(safe->safe_size > 0) {	dummy = (SEC_PKCS12SafeBag **)PORT_ArenaGrow(safe->poolp, 	    				safe->contents, 	    				size, 	    				(size + sizeof(SEC_PKCS12SafeBag *)));	safe->contents = dummy;    } else {	safe->contents = (SEC_PKCS12SafeBag **)PORT_ArenaZAlloc(safe->poolp, 	    (2 * sizeof(SEC_PKCS12SafeBag *)));	dummy = safe->contents;    }    if(dummy == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    safe->contents[safe->safe_size] = bag;    safe->safe_size++;    safe->contents[safe->safe_size] = NULL;    PORT_ArenaUnmark(safe->poolp, mark);    return SECSuccess;loser:    PORT_ArenaRelease(safe->poolp, mark);    return SECFailure;}/* append a certificate onto the end of a cert bag */static SECStatus sec_pkcs12_append_cert_to_bag(PRArenaPool *arena,			      SEC_PKCS12SafeBag *safebag,			      CERTCertificate *cert,			      SECItem *nickname){    int size;    void *dummy = NULL, *mark = NULL;    SEC_PKCS12CertAndCRL *p12cert;    SEC_PKCS12CertAndCRLBag *bag;    if((arena == NULL) || (safebag == NULL) ||     	(cert == NULL) || (nickname == NULL)) {	return SECFailure;    }    bag = safebag->safeContent.certAndCRLBag;    if(bag == NULL) {	return SECFailure;    }    mark = PORT_ArenaMark(arena);    p12cert = sec_pkcs12_get_cert(arena, cert, nickname);    if(p12cert == NULL) {	PORT_ArenaRelease(bag->poolp, mark);	return SECFailure;    }    size = bag->bag_size * sizeof(SEC_PKCS12CertAndCRL *);    if(bag->bag_size > 0) {	dummy = (SEC_PKCS12CertAndCRL **)PORT_ArenaGrow(bag->poolp,	    bag->certAndCRLs, size, size + sizeof(SEC_PKCS12CertAndCRL *));	bag->certAndCRLs = dummy;    } else {	bag->certAndCRLs = (SEC_PKCS12CertAndCRL **)PORT_ArenaZAlloc(bag->poolp,	    (2 * sizeof(SEC_PKCS12CertAndCRL *)));	dummy = bag->certAndCRLs;    }    if(dummy == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    bag->certAndCRLs[bag->bag_size] = p12cert;    bag->bag_size++;    bag->certAndCRLs[bag->bag_size] = NULL;    PORT_ArenaUnmark(bag->poolp, mark);    return SECSuccess;loser:    PORT_ArenaRelease(bag->poolp, mark);    return SECFailure;}/* append a key onto the end of a list of keys in a key bag */SECStatus sec_pkcs12_append_key_to_bag(SEC_PKCS12SafeBag *safebag,			     SEC_PKCS12PrivateKey *pk){    void *mark, *dummy;    SEC_PKCS12PrivateKeyBag *bag;    int size;    if((safebag == NULL) || (pk == NULL))	return SECFailure;    bag = safebag->safeContent.keyBag;    if(bag == NULL) {	return SECFailure;    }    mark = PORT_ArenaMark(bag->poolp);    size = (bag->bag_size * sizeof(SEC_PKCS12PrivateKey *));    if(bag->bag_size > 0) {	dummy = (SEC_PKCS12PrivateKey **)PORT_ArenaGrow(bag->poolp,					bag->privateKeys, 					size, 					size + sizeof(SEC_PKCS12PrivateKey *));	bag->privateKeys = dummy;    } else {	bag->privateKeys = (SEC_PKCS12PrivateKey **)PORT_ArenaZAlloc(bag->poolp,	    (2 * sizeof(SEC_PKCS12PrivateKey *)));	dummy = bag->privateKeys;    }    if(dummy == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    bag->privateKeys[bag->bag_size] = pk;    bag->bag_size++;    bag->privateKeys[bag->bag_size] = NULL;    PORT_ArenaUnmark(bag->poolp, mark);    return SECSuccess;loser:    /* XXX Free memory? */    PORT_ArenaRelease(bag->poolp, mark);    return SECFailure;}/* append a safe bag to the baggage area */static SECStatus sec_pkcs12_append_unshrouded_bag(SEC_PKCS12BaggageItem *bag,				 SEC_PKCS12SafeBag *u_bag){    int size;    void *mark = NULL, *dummy = NULL;    if((bag == NULL) || (u_bag == NULL))	return SECFailure;    mark = PORT_ArenaMark(bag->poolp);    /* dump things into the first bag */    size = (bag->nSecrets + 1) * sizeof(SEC_PKCS12SafeBag *);    dummy = PORT_ArenaGrow(bag->poolp,	    		bag->unencSecrets, size, 	    		size + sizeof(SEC_PKCS12SafeBag *));    bag->unencSecrets = dummy;    if(dummy == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    bag->unencSecrets[bag->nSecrets] = u_bag;    bag->nSecrets++;    bag->unencSecrets[bag->nSecrets] = NULL;    PORT_ArenaUnmark(bag->poolp, mark);    return SECSuccess;loser:    PORT_ArenaRelease(bag->poolp, mark);    return SECFailure;}/* gather up all certificates and keys and package them up * in the safe, baggage, or both. * nicknames is the list of nicknames and corresponding certs in ref_certs * ref_certs a null terminated list of certificates * rSafe, rBaggage -- return areas for safe and baggage * shroud_keys -- store keys externally * pwitem -- password for computing integrity mac and encrypting contents * wincx -- window handle * * if a failure occurs, an error is set and SECFailure returned. */static SECStatussec_pkcs12_package_certs_and_keys(SECItem **nicknames,				  CERTCertificate **ref_certs,				  PRBool unencryptedCerts,				  SEC_PKCS12SafeContents **rSafe,				  SEC_PKCS12Baggage **rBaggage,				  PRBool shroud_keys, 				  SECOidTag shroud_alg,				  SECItem *pwitem,				  PKCS12UnicodeConvertFunction unicodeFn,				  void *wincx){    PRArenaPool *permArena;    SEC_PKCS12SafeContents *safe = NULL;    SEC_PKCS12Baggage *baggage = NULL;    SECStatus rv = SECFailure;    PRBool problem = PR_FALSE;    SEC_PKCS12ESPVKItem *espvk = NULL;    SEC_PKCS12PrivateKey *pk = NULL;    CERTCertificate *add_cert = NULL;    SEC_PKCS12SafeBag *certbag = NULL, *keybag = NULL;    SEC_PKCS12BaggageItem *external_bag = NULL;    int ncerts = 0, nkeys = 0;    int i;    if((nicknames == NULL) || (rSafe == NULL) || (rBaggage == NULL)) {	return SECFailure;    }	    *rBaggage = baggage;    *rSafe = safe;    permArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    if(permArena == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;     }    /* allocate structures */    safe = sec_pkcs12_create_safe_contents(permArena);    if(safe == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	rv = SECFailure;	goto loser;    }    certbag = sec_pkcs12_create_safe_bag(permArena, 					 SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID);    if(certbag == NULL) {	rv = SECFailure;	goto loser;    }    if(shroud_keys != PR_TRUE) {	keybag = sec_pkcs12_create_safe_bag(permArena, 					    SEC_OID_PKCS12_KEY_BAG_ID);	if(keybag == NULL) {	    rv = SECFailure;	    goto loser;	}    }    if((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) {	baggage = sec_pkcs12_create_baggage(permArena);    	if(baggage == NULL) {	    rv = SECFailure;	    goto loser;	}	external_bag = sec_pkcs12_create_external_bag(baggage);    }    /* package keys and certs */    i = 0;    while((nicknames[i] != NULL) && (problem == PR_FALSE)) {	if(ref_certs[i] != NULL) {	    /* append cert to bag o certs */	    rv = sec_pkcs12_append_cert_to_bag(permArena, certbag, 	    				       ref_certs[i],	    				       nicknames[i]);	    if(rv == SECFailure) {		problem = PR_FALSE;	    } else {		ncerts++;	    }	    if(rv == SECSuccess) {		/* package up them keys */		if(shroud_keys == PR_TRUE) {	    	    espvk = sec_pkcs12_get_shrouded_key(permArena, 							nicknames[i],	    	    					ref_certs[i],							shroud_alg, 							pwitem, unicodeFn,							wincx);		    if(espvk != NULL) {			rv = sec_pkcs12_append_shrouded_key(external_bag, espvk);			SECITEM_CopyItem(permArena, &espvk->derCert,					 &ref_certs[i]->derCert);		    } else {			rv = SECFailure;		    }		} else {		    pk = sec_pkcs12_get_private_key(permArena, nicknames[i], 		    				    ref_certs[i], wincx);		    if(pk != NULL) {			rv = sec_pkcs12_append_key_to_bag(keybag, pk);			SECITEM_CopyItem(permArena, &espvk->derCert,					 &ref_certs[i]->derCert);		    } else {			rv = SECFailure;		    }		}			if(rv == SECFailure) {		    problem = PR_TRUE;		} else {		    nkeys++;		}	    }	} else {	    /* handle only keys here ? */	    problem = PR_TRUE;	}	i++;    }    /* let success fall through */loser:    if(problem == PR_FALSE) {	/* if we have certs, we want to append the cert bag to the 	 * appropriate area 	 */	if(ncerts > 0) {	    if(unencryptedCerts != PR_TRUE) {		rv = sec_pkcs12_append_safe_bag(safe, certbag);	    } else {		rv = sec_pkcs12_append_unshrouded_bag(external_bag, certbag);	    }	} else {	    rv = SECSuccess;	}	/* append key bag, if they are stored in safe contents */	if((rv == SECSuccess) && (shroud_keys == PR_FALSE) && (nkeys > 0)) {	    rv = sec_pkcs12_append_safe_bag(safe, keybag);	}    } else {	rv = SECFailure;    }    /* if baggage not used, NULLify it */    if((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) {	if(((unencryptedCerts == PR_TRUE) && (ncerts == 0)) &&	   ((shroud_keys == PR_TRUE) && (nkeys == 0)))		baggage = NULL;    } else {	baggage = NULL;    }    if((problem == PR_TRUE) || (rv == SECFailure)) {	PORT_FreeArena(permArena, PR_TRUE);	rv = SECFailure;	baggage = NULL;	safe = NULL;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?