keydb.c

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

C
2,311
字号
SECKEYEncryptedPrivateKeyInfo *seckey_encrypt_private_key(	SECKEYLowPrivateKey *pk, SECItem *pwitem, SECKEYKeyDBHandle *keydb,	SECOidTag algorithm){    SECKEYEncryptedPrivateKeyInfo *epki = NULL;    SECKEYPrivateKeyInfo *pki = NULL;    SECStatus rv = SECFailure;    SECAlgorithmID *algid = NULL;    PLArenaPool *temparena = NULL, *permarena = NULL;    SECItem *key = NULL, *salt = NULL, *der_item = NULL;    SECItem *dummy = NULL, *dest = NULL;    permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    if(permarena == NULL)	return NULL;    temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    if(temparena == NULL)	goto loser;    /* allocate structures */    epki = (SECKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(permarena,	sizeof(SECKEYEncryptedPrivateKeyInfo));    pki = (SECKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena, 	sizeof(SECKEYPrivateKeyInfo));    der_item = (SECItem *)PORT_ArenaZAlloc(temparena, sizeof(SECItem));    if((epki == NULL) || (pki == NULL) || (der_item == NULL))	goto loser;    epki->arena = permarena;    /* setup private key info */    dummy = SEC_ASN1EncodeInteger(temparena, &(pki->version), 	SEC_PRIVATE_KEY_INFO_VERSION);    if(dummy == NULL)	goto loser;    /* Encode the key, and set the algorithm (with params) */    switch (pk->keyType) {      case rsaKey:	dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, 				   SECKEY_RSAPrivateKeyTemplate);	if (dummy == NULL) {	    rv = SECFailure;	    goto loser;	}		rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm), 				   SEC_OID_PKCS1_RSA_ENCRYPTION, 0);	if (rv == SECFailure) {	    goto loser;	}		break;      case dsaKey:	dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,				   SECKEY_DSAPrivateKeyTemplate);	if (dummy == NULL) {	    rv = SECFailure;	    goto loser;	}		dummy = SEC_ASN1EncodeItem(temparena, NULL, &pk->u.dsa.params,				   SECKEY_PQGParamsTemplate);	if (dummy == NULL) {	    rv = SECFailure;	    goto loser;	}		rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm),				   SEC_OID_ANSIX9_DSA_SIGNATURE, dummy);	if (rv == SECFailure) {	    goto loser;	}		break;      case dhKey:	dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,				   SECKEY_DHPrivateKeyTemplate);	if (dummy == NULL) {	    rv = SECFailure;	    goto loser;	}	rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm),				   SEC_OID_X942_DIFFIE_HELMAN_KEY, dummy);	if (rv == SECFailure) {	    goto loser;	}	break;      default:	/* We don't support DH or Fortezza private keys yet */	PORT_Assert(PR_FALSE);	break;    }    /* setup encrypted private key info */    dummy = SEC_ASN1EncodeItem(temparena, der_item, pki, 	SECKEY_PrivateKeyInfoTemplate);    if(dummy == NULL) {	rv = SECFailure;	goto loser;    }    rv = SECFailure; /* assume failure */    switch(algorithm)    {	case SEC_OID_RC4:	    salt = seckey_create_rc4_salt();	    if(salt != NULL)	    {		key = seckey_create_rc4_key(pwitem, salt);		if(key != NULL)		{		    dest = seckey_rc4_cipher(key, der_item, PR_TRUE);		    if(dest != NULL)		    {			rv = SECITEM_CopyItem(permarena, &epki->encryptedData,			    dest);			if(rv == SECSuccess)			rv = SECOID_SetAlgorithmID(permarena, 			&epki->algorithm, SEC_OID_RC4, salt);		    }		}	    }	    if(dest != NULL)		SECITEM_FreeItem(dest, PR_TRUE);	    if(key != NULL)		SECITEM_ZfreeItem(key, PR_TRUE);	    break;	default:	    algid = SEC_PKCS5CreateAlgorithmID(algorithm, NULL, 1);	    if(algid != NULL)	    {		dest = SEC_PKCS5CipherData(algid, pwitem, 		der_item, PR_TRUE, NULL);		if(dest != NULL)		{		    rv = SECITEM_CopyItem(permarena, &epki->encryptedData,			    dest);		    if(rv == SECSuccess)			rv = SECOID_CopyAlgorithmID(permarena, 			    &epki->algorithm, algid);		}	    }	    if(dest != NULL)		SECITEM_FreeItem(dest, PR_TRUE);	    if(algid != NULL)		SECOID_DestroyAlgorithmID(algid, PR_TRUE);	    break;    }    /* let success fall through */loser:    if(rv == SECFailure)    {	PORT_FreeArena(permarena, PR_TRUE);	    epki = NULL;    }    if(temparena != NULL)	PORT_FreeArena(temparena, PR_TRUE);	    if(salt != NULL)	SECITEM_FreeItem(salt, PR_TRUE);    return epki;}SECStatus seckey_put_private_key(SECKEYKeyDBHandle *keydb, DBT *index, SECItem *pwitem,		       SECKEYLowPrivateKey *pk, char *nickname, PRBool update,		       SECOidTag algorithm){    SECKEYDBKey *dbkey = NULL;    SECKEYEncryptedPrivateKeyInfo *epki = NULL;    PLArenaPool *temparena = NULL, *permarena = NULL;    SECItem *dummy = NULL;    SECItem *salt = NULL;    SECStatus rv = SECFailure;    if((keydb == NULL) || (index == NULL) || (pwitem == NULL) ||	(pk == NULL))	return SECFailure;	    permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    if(permarena == NULL)	return SECFailure;    dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(permarena, sizeof(SECKEYDBKey));    if(dbkey == NULL)	goto loser;    dbkey->arena = permarena;    dbkey->nickname = nickname;    /* TNH - for RC4, the salt should be created here */	    epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm);    if(epki == NULL)	goto loser;    temparena = epki->arena;    /* extract salt for db key */    switch(algorithm)    {	case SEC_OID_RC4:	    rv = SECITEM_CopyItem(permarena, &(dbkey->salt), 		&(epki->algorithm.parameters));	    epki->algorithm.parameters.len = 0;		epki->algorithm.parameters.data = NULL;	    break;	default:            /* TNH - this should not be necessary */	    salt = SEC_PKCS5GetSalt(&epki->algorithm);	    if(salt != NULL)	    {		rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt);		SECITEM_ZfreeItem(salt, PR_TRUE);	    }	    break;    }    dummy = SEC_ASN1EncodeItem(permarena, &(dbkey->derPK), epki, 	SECKEY_EncryptedPrivateKeyInfoTemplate);    if(dummy == NULL)	rv = SECFailure;    else	rv = put_dbkey(keydb, index, dbkey, update);    /* let success fall through */loser:    if(rv != SECSuccess)	if(permarena != NULL)	    PORT_FreeArena(permarena, PR_TRUE);    if(temparena != NULL)	PORT_FreeArena(temparena, PR_TRUE);    return rv;}/* * Store a key in the database, indexed by its public key modulus. * Note that the nickname is optional.  It was only used by keyutil. */SECStatusSECKEY_StoreKeyByPublicKeyAlg(SECKEYKeyDBHandle *handle, 			      SECKEYLowPrivateKey *privkey,			      SECItem *pubKeyData,			      char *nickname,			      SECKEYGetPasswordKey f, void *arg,			      SECOidTag algorithm){    DBT namekey;    SECItem *pwitem = NULL;    SECStatus rv;    if (handle == NULL) {	PORT_SetError(SEC_ERROR_BAD_DATABASE);	return(SECFailure);    }    /* set up db key and data */    namekey.data = pubKeyData->data;    namekey.size = pubKeyData->len;    pwitem = (*f )(arg, handle);    if ( pwitem == NULL ) {	return(SECFailure);    }        /* encrypt the private key */    rv = seckey_put_private_key(handle, &namekey, pwitem, privkey, nickname,				PR_FALSE, algorithm);    SECITEM_ZfreeItem(pwitem, PR_TRUE);        return(rv);}SECKEYLowPrivateKey *seckey_decrypt_private_key(SECKEYEncryptedPrivateKeyInfo *epki,			   SECItem *pwitem){    SECKEYLowPrivateKey *pk = NULL;    SECKEYPrivateKeyInfo *pki = NULL;    SECStatus rv = SECFailure;    SECOidTag algorithm;    PLArenaPool *temparena = NULL, *permarena = NULL;    SECItem *salt = NULL, *dest = NULL, *key = NULL;    if((epki == NULL) || (pwitem == NULL))	goto loser;    temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);    if((temparena == NULL) || (permarena == NULL))	goto loser;    /* allocate temporary items */    pki = (SECKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena, 	sizeof(SECKEYPrivateKeyInfo));    /* allocate permanent arena items */    pk = (SECKEYLowPrivateKey *)PORT_ArenaZAlloc(permarena,	sizeof(SECKEYLowPrivateKey));    if((pk == NULL) || (pki == NULL))	goto loser;    pk->arena = permarena;	    algorithm = SECOID_GetAlgorithmTag(&(epki->algorithm));    switch(algorithm)    {	case SEC_OID_RC4:	    salt = SECITEM_DupItem(&epki->algorithm.parameters);	    if(salt != NULL)	    {		key = seckey_create_rc4_key(pwitem, salt);		if(key != NULL)		{		    dest = seckey_rc4_cipher(key, &epki->encryptedData, 			PR_FALSE);		}	    }		    if(salt != NULL)		SECITEM_ZfreeItem(salt, PR_TRUE);	    if(key != NULL)		SECITEM_ZfreeItem(key, PR_TRUE);	    break;	default:	    /* we depend on the fact that if this key was encoded with	     * DES, that the pw was also encoded with DES, so we don't have	     * to do the update here, the password code will handle it. */	    dest = SEC_PKCS5CipherData(&epki->algorithm, pwitem, 		&epki->encryptedData, PR_FALSE, NULL);	    break;    }    if(dest != NULL)    {	rv = SEC_ASN1DecodeItem(temparena, pki, 	    SECKEY_PrivateKeyInfoTemplate, dest);	if(rv == SECSuccess)	{	    switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {	      case SEC_OID_X500_RSA_ENCRYPTION:	      case SEC_OID_PKCS1_RSA_ENCRYPTION:		pk->keyType = rsaKey;		rv = SEC_ASN1DecodeItem(permarena, pk,					SECKEY_RSAPrivateKeyTemplate,					&pki->privateKey);		break;	      case SEC_OID_ANSIX9_DSA_SIGNATURE:		pk->keyType = dsaKey;		rv = SEC_ASN1DecodeItem(permarena, pk,					SECKEY_DSAPrivateKeyTemplate,					&pki->privateKey);		if (rv != SECSuccess)		    goto loser;		rv = SEC_ASN1DecodeItem(permarena, &pk->u.dsa.params,					SECKEY_PQGParamsTemplate,					&pki->algorithm.parameters);		break;	      case SEC_OID_X942_DIFFIE_HELMAN_KEY:		pk->keyType = dhKey;		rv = SEC_ASN1DecodeItem(permarena, pk,					SECKEY_DHPrivateKeyTemplate,					&pki->privateKey);		break;	      default:		rv = SECFailure;		break;	    }	}	else if(PORT_GetError() == SEC_ERROR_BAD_DER)	{	    PORT_SetError(SEC_ERROR_BAD_PASSWORD);	    goto loser;	}    }    /* let success fall through */loser:    if(temparena != NULL)	PORT_FreeArena(temparena, PR_TRUE);    if(dest != NULL)	SECITEM_ZfreeItem(dest, PR_TRUE);    if(rv != SECSuccess)    {	if(permarena != NULL)	    PORT_FreeArena(permarena, PR_TRUE);	pk = NULL;    }    return pk;}static SECKEYLowPrivateKey *seckey_decode_encrypted_private_key(SECKEYDBKey *dbkey, SECItem *pwitem){    SECKEYLowPrivateKey *pk = NULL;    SECKEYEncryptedPrivateKeyInfo *epki;    PLArenaPool *temparena = NULL;    SECStatus rv;    SECOidTag algorithm;    if( ( dbkey == NULL ) || ( pwitem == NULL ) ) {	return NULL;    }    temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if(temparena == NULL) {	return NULL;    }    epki = (SECKEYEncryptedPrivateKeyInfo *)	PORT_ArenaZAlloc(temparena, sizeof(SECKEYEncryptedPrivateKeyInfo));    if(epki == NULL) {	goto loser;    }    rv = SEC_ASN1DecodeItem(temparena, epki,			    SECKEY_EncryptedPrivateKeyInfoTemplate,			    &(dbkey->derPK));     if(rv != SECSuccess) {	goto loser;    }    algorithm = SECOID_GetAlgorithmTag(&(epki->algorithm));    switch(algorithm)    {      case SEC_OID_RC4:	/* TNH - this code should derive the actual RC4 key from salt and           pwitem */	rv = SECITEM_CopyItem(temparena, &(epki->algorithm.parameters),			      &(dbkey->salt));	break;      default:	break;    }    pk = seckey_decrypt_private_key(epki, pwitem);    /* let success fall through */loser:    PORT_FreeArena(temparena, PR_TRUE);    return pk;}SECKEYLowPrivateKey *seckey_get_private_key(SECKEYKeyDBHandle *keydb, DBT *index, char **nickname,		       SECItem *pwitem){    SECKEYDBKey *dbkey = NULL;    SECKEYLowPrivateKey *pk = NULL;    if( ( keydb == NULL ) || ( index == NULL ) || ( pwitem == NULL ) ) {	return NULL;    }    dbkey = get_dbkey(keydb, index);    if(dbkey == NULL) {	goto loser;    }        if ( nickname ) {	if ( dbkey->nickname && ( dbkey->nickname[0] != 0 ) ) {	    *nickname = PORT_Strdup(dbkey->nickname);	} else {	    *nickname = NULL;	}    }        pk = seckey_decode_encrypted_private_key(dbkey, pwitem);        /* let success fall through */loser:    if ( dbkey != NULL ) {	sec_destroy_dbkey(dbkey);    }    return pk;}/* * used by pkcs11 to import keys into it's object format... In the future * we really need a better way to tie in... */SECKEYLowPrivateKey *SECKEY_DecryptKey(DBT *key, SECItem *pwitem,					 SECKEYKeyDBHandle *handle) {    return seckey_get_private_key(handle,key,NULL,pwitem);}/* * Find a key in the database, indexed by its public key modulus * This is used to find keys that have been stored before their * certificate arrives.  Once the certificate arrives the key * is looked up by the public modulus in the certificate, and the * re-stored by its nickname. */SECKEYLowPrivateKey *SECKEY_FindKeyByPublicKey(SECKEYKeyDBHandle *handle, SECItem *modulus,			  SECKEYGetPasswordKey f, void *arg){    DBT namekey;    SECKEYLowPrivateKey *pk = NULL;    SECItem *pwitem = NULL;    if (handle == NULL) {	PORT_SetError(SEC_ERROR_BAD_DATABASE);	return NULL;    }    /* set up db key */    namekey.data = modulus->data;    namekey.size = modulus->len;    pwitem = (*f )(arg, handle);    if ( pwitem == NULL ) {	return(NULL);    }    pk = seckey_get_private_key(handle, &namekey, NULL, pwitem);    SECITEM_ZfreeItem(pwitem, PR_TRUE);        /* no need to free dbkey, since its on the stack, and the data it     * points to is owned by the database     */    return(pk);}/* ===== ENCODING ROUTINES ===== */static SECStatusencodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg,		   SECItem *encCheck){    SECOidData *oidData;    SECStatus rv;        oidData = SECOID_FindOIDByTag(alg);    if ( oidData == NULL ) {	rv = SECFailure;	goto loser;    }    entry->len = 1 + oidData->oid.len + encCheck->len;    if ( arena ) {	entry->data = (unsigned char *)PORT_ArenaAlloc(arena, entry->len);    } else {	entry->data = (unsigned char *)PORT_Alloc(entry->len);    }        if ( entry->data == NULL ) {	goto loser;    }	    /* first length of oid */    entry->data[0] = (unsigned char)oidData->oid.len;    /* next oid itself */    PORT_Memcpy(&entry->data[1], oidData->oid.data, oidData->oid.len);    /* finally the encrypted check string */    PORT_Memcpy(&entry->data[1+oidData->oid.len], encCheck->data,		encCheck->len);    return(SECSuccess);loser:    return(SECFailure);}

⌨️ 快捷键说明

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