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 + -
显示快捷键?