keydb.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,311 行 · 第 1/4 页
C
2,311 行
} else { openflags = O_RDWR; } dbname = (*namecb)(cbarg, PRIVATE_KEY_DB_FILE_VERSION); if ( dbname == NULL ) { goto loser; } handle->db = dbopen( dbname, openflags, 0600, DB_HASH, 0 ); /* check for correct version number */ if (handle->db != NULL) { /* lookup version string in database */ rv = (* handle->db->get)( handle->db, &versionKey, &versionData, 0 ); /* error accessing the database */ if ( rv < 0 ) { goto loser; } if ( rv == 1 ) { /* no version number record, reset the database */ (* handle->db->close)( handle->db ); handle->db = NULL; goto newdb; } handle->version = *( (unsigned char *)versionData.data); if (handle->version != PRIVATE_KEY_DB_FILE_VERSION ) { /* bogus version number record, reset the database */ (* handle->db->close)( handle->db ); handle->db = NULL; goto newdb; } }newdb: /* if first open fails, try to create a new DB */ if ( handle->db == NULL ) { if ( readOnly ) { goto loser; } handle->db = dbopen( dbname, O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); PORT_Free( dbname ); dbname = NULL; /* if create fails then we lose */ if ( handle->db == NULL ) { goto loser; } rv = makeGlobalVersion(handle); if ( rv != SECSuccess ) { goto loser; } /* * try to update from v2 db */ dbname = (*namecb)(cbarg, 2); if ( dbname != NULL ) { handle->updatedb = dbopen( dbname, O_RDONLY, 0600, DB_HASH, 0 ); if ( handle->updatedb ) { /* * Try to update the db using a null password. If the db * doesn't have a password, then this will work. If it does * have a password, then this will fail and we will do the * update later */ rv = SECKEY_UpdateKeyDBPass1(handle); if ( rv == SECSuccess ) { updated = PR_TRUE; } } PORT_Free( dbname ); dbname = NULL; } /* we are using the old salt if we updated from an old db */ if ( ! updated ) { rv = makeGlobalSalt(handle); if ( rv != SECSuccess ) { goto loser; } } /* sync the database */ rv = (* handle->db->sync)(handle->db, 0); if ( rv ) { goto loser; } } handle->global_salt = GetKeyDBGlobalSalt(handle); if ( dbname ) PORT_Free( dbname ); return handle;loser: if ( dbname ) PORT_Free( dbname ); PORT_SetError(SEC_ERROR_BAD_DATABASE); if ( handle->db ) { (* handle->db->close)(handle->db); } if ( handle->updatedb ) { (* handle->updatedb->close)(handle->updatedb); } PORT_Free(handle); return NULL;}/* * Close the database */voidSECKEY_CloseKeyDB(SECKEYKeyDBHandle *handle){ if (handle != NULL) { if (handle == SECKEY_GetDefaultKeyDB()) { SECKEY_SetDefaultKeyDB(NULL); } if (handle->db != NULL) { (* handle->db->close)(handle->db); } PORT_Free(handle); }}/* Get the key database version */intSECKEY_GetKeyDBVersion(SECKEYKeyDBHandle *handle){ PORT_Assert(handle != NULL); return handle->version;}/* * Allow use of default key database, so that apps (such as mozilla) do * not have to pass the handle all over the place. */static SECKEYKeyDBHandle *sec_default_key_db = NULL;voidSECKEY_SetDefaultKeyDB(SECKEYKeyDBHandle *handle){ sec_default_key_db = handle;}SECKEYKeyDBHandle *SECKEY_GetDefaultKeyDB(void){ return sec_default_key_db;}/* * Delete a private key that was stored in the database */SECStatusSECKEY_DeleteKey(SECKEYKeyDBHandle *handle, SECItem *pubkey){ DBT namekey; int rv; if (handle == NULL) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return(SECFailure); } /* set up db key and data */ namekey.data = pubkey->data; namekey.size = pubkey->len; /* delete it from the database */ rv = (* handle->db->del)(handle->db, &namekey, 0); if ( rv ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return(SECFailure); } /* sync the database */ rv = (* handle->db->sync)(handle->db, 0); if ( rv ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return(SECFailure); } return(SECSuccess);}/* * Store a key in the database, indexed by its public key modulus.(value!) */SECStatusSECKEY_StoreKeyByPublicKey(SECKEYKeyDBHandle *handle, SECKEYLowPrivateKey *privkey, SECItem *pubKeyData, char *nickname, SECKEYGetPasswordKey f, void *arg){ return SECKEY_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData, nickname, f, arg, SECKEY_GetDefaultKeyDBAlg());}/* see if the public key for this cert is in the database filed * by modulus */SECStatusSECKEY_KeyForCertExists(SECKEYKeyDBHandle *handle, CERTCertificate *cert){ SECKEYPublicKey *pubkey = NULL; DBT namekey; DBT dummy; int status; /* get cert's public key */ pubkey = CERT_ExtractPublicKey(cert); if ( pubkey == NULL ) { return SECFailure; } /* TNH - make key from SECKEYPublicKey */ switch (pubkey->keyType) { case rsaKey: namekey.data = pubkey->u.rsa.modulus.data; namekey.size = pubkey->u.rsa.modulus.len; break; case dsaKey: namekey.data = pubkey->u.dsa.publicValue.data; namekey.size = pubkey->u.dsa.publicValue.len; break; case dhKey: namekey.data = pubkey->u.dh.publicValue.data; namekey.size = pubkey->u.dh.publicValue.len; break; default: /* XXX We don't do Fortezza or DH yet. */ return SECFailure; } status = (* handle->db->get)(handle->db, &namekey, &dummy, 0); SECKEY_DestroyPublicKey(pubkey); if ( status ) { /* TNH - should this really set an error? */ PORT_SetError(SEC_ERROR_BAD_DATABASE); return SECFailure; } return SECSuccess;}/* * find the private key for a cert */SECKEYLowPrivateKey *SECKEY_FindKeyByCert(SECKEYKeyDBHandle *handle, CERTCertificate *cert, SECKEYGetPasswordKey f, void *arg){ SECKEYPublicKey *pubkey = NULL; SECItem *keyItem; SECKEYLowPrivateKey *privKey = NULL; /* get cert's public key */ pubkey = CERT_ExtractPublicKey(cert); if ( !pubkey ) { goto loser; } /* TNH - make record key from SECKEYPublicKey (again) */ switch (pubkey->keyType) { case rsaKey: keyItem = &pubkey->u.rsa.modulus; break; case dsaKey: keyItem = &pubkey->u.dsa.publicValue; break; case dhKey: keyItem = &pubkey->u.dh.publicValue; break; /* fortezza an NULL keys are not stored in the data base */ case fortezzaKey: case nullKey: goto loser; } privKey = SECKEY_FindKeyByPublicKey(handle, keyItem, f, arg); /* success falls through */loser: SECKEY_DestroyPublicKey(pubkey); return(privKey);}/* * check to see if the user has a password */SECStatusSECKEY_HasKeyDBPassword(SECKEYKeyDBHandle *handle){ DBT checkkey, checkdata; int rv; if (handle == NULL) { return(SECFailure); } checkkey.data = KEYDB_PW_CHECK_STRING; checkkey.size = KEYDB_PW_CHECK_LEN; rv = (* handle->db->get)(handle->db, &checkkey, &checkdata, 0 ); if ( rv ) { return(SECFailure); } return(SECSuccess);}/* * Set up the password checker in the key database. * This is done by encrypting a known plaintext with the user's key. */SECStatusSECKEY_SetKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem){ return SECKEY_SetKeyDBPasswordAlg(handle, pwitem, SECKEY_GetDefaultKeyDBAlg());}/* * Re-encrypt the entire key database with a new password. * NOTE: This really should create a new database rather than doing it * in place in the original */SECStatusSECKEY_ChangeKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *oldpwitem, SECItem *newpwitem){ return SECKEY_ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, SECKEY_GetDefaultKeyDBAlg());}static SECStatusHashPassword(unsigned char *hashresult, char *pw, SECItem *salt){ SHA1Context *cx; unsigned int outlen; cx = SHA1_NewContext(); if ( cx == NULL ) { return(SECFailure); } SHA1_Begin(cx); if ( ( salt != NULL ) && ( salt->data != NULL ) ) { SHA1_Update(cx, salt->data, salt->len); } SHA1_Update(cx, (unsigned char *)pw, PORT_Strlen(pw)); SHA1_End(cx, hashresult, &outlen, SHA1_LENGTH); SHA1_DestroyContext(cx, PR_TRUE); return(SECSuccess);}SECItem *SECKEY_HashPassword(char *pw, SECItem *salt){ SECItem *pwitem; SECStatus rv; pwitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if ( pwitem == NULL ) { return(NULL); } pwitem->len = SHA1_LENGTH; pwitem->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH); if ( pwitem->data == NULL ) { PORT_Free(pwitem); return(NULL); } if ( pw ) { rv = HashPassword(pwitem->data, pw, salt); if ( rv != SECSuccess ) { SECITEM_ZfreeItem(pwitem, PR_TRUE); return(NULL); } } return(pwitem);}/* Derive the actual password value for the database from a pw string */SECItem *SECKEY_DeriveKeyDBPassword(SECKEYKeyDBHandle *keydb, char *pw){ PORT_Assert(keydb != NULL); PORT_Assert(pw != NULL); if (keydb == NULL || pw == NULL) return(NULL); return SECKEY_HashPassword(pw, keydb->global_salt);}#if 0/* Appears obsolete - TNH *//* get the algorithm with which a private key * is encrypted. */SECOidTag seckey_get_private_key_algorithm(SECKEYKeyDBHandle *keydb, DBT *index) { SECKEYDBKey *dbkey = NULL; SECOidTag algorithm = SEC_OID_UNKNOWN; SECKEYEncryptedPrivateKeyInfo *epki = NULL; PLArenaPool *poolp = NULL; SECStatus rv; poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if(poolp == NULL) return (SECOidTag)SECFailure; /* TNH - this is bad */ dbkey = get_dbkey(keydb, index); if(dbkey == NULL) return (SECOidTag)SECFailure; epki = (SECKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp, sizeof(SECKEYEncryptedPrivateKeyInfo)); if(epki == NULL) goto loser; rv = SEC_ASN1DecodeItem(poolp, epki, SECKEY_EncryptedPrivateKeyInfoTemplate, &dbkey->derPK); if(rv == SECFailure) goto loser; algorithm = SECOID_GetAlgorithmTag(&epki->algorithm); /* let success fall through */loser: if(poolp != NULL) PORT_FreeArena(poolp, PR_TRUE);\ if(dbkey != NULL) sec_destroy_dbkey(dbkey); return algorithm;}#endif /* * Derive an RC4 key from a password key and a salt. This * was the method to used to encrypt keys in the version 2? * database */SECItem *seckey_create_rc4_key(SECItem *pwitem, SECItem *salt){ MD5Context *md5 = NULL; unsigned int part; SECStatus rv = SECFailure; SECItem *key = NULL; key = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if(key != NULL) { key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * MD5_LENGTH); key->len = MD5_LENGTH; if(key->data != NULL) { md5 = MD5_NewContext(); if ( md5 != NULL ) { MD5_Begin(md5); MD5_Update(md5, salt->data, salt->len); MD5_Update(md5, pwitem->data, pwitem->len); MD5_End(md5, key->data, &part, MD5_LENGTH); MD5_DestroyContext(md5, PR_TRUE); rv = SECSuccess; } } if(rv != SECSuccess) { SECITEM_FreeItem(key, PR_TRUE); key = NULL; } } return key;}SECItem *seckey_create_rc4_salt(void){ SECItem *salt = NULL; SECStatus rv = SECFailure; salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if(salt == NULL) return NULL; salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * SALT_LENGTH); if(salt->data != NULL) { salt->len = SALT_LENGTH; RNG_GenerateGlobalRandomBytes(salt->data, salt->len); rv = SECSuccess; } if(rv == SECFailure) { SECITEM_FreeItem(salt, PR_TRUE); salt = NULL; } return salt;}SECItem *seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt){ SECItem *dest = NULL; RC4Context *ctxt = NULL; SECStatus rv = SECFailure; if((key == NULL) || (src == NULL)) return NULL; dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if(dest == NULL) return NULL; dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * (src->len + 64)); /* TNH - padding? */ if(dest->data != NULL) { ctxt = RC4_CreateContext(key->data, key->len); if(ctxt != NULL) { if(encrypt == PR_TRUE) rv = RC4_Encrypt(ctxt, dest->data, &dest->len, src->len + 64, src->data, src->len); else rv = RC4_Decrypt(ctxt, dest->data, &dest->len, src->len + 64, src->data, src->len); RC4_DestroyContext(ctxt, PR_TRUE); } } if(rv == SECFailure) if(dest != NULL) { SECITEM_FreeItem(dest, PR_TRUE); dest = NULL; } return dest;}/* TNH - keydb is unused *//* TNH - the pwitem should be the derived key for RC4 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?