keydb.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,311 行 · 第 1/4 页
C
2,311 行
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. * * Private Key Database code * * $Id: keydb.c,v 1.3 2000/10/01 17:13:34 wtc%netscape.com Exp $ */#include "keylow.h"#include "keydbt.h"#include "seccomon.h"#include "sechash.h"#include "secder.h"#include "secasn1.h"#include "secoid.h"#include "blapi.h"#include "secitem.h"#include "cert.h"#include "mcom_db.h"#include "secpkcs5.h"#include "secerr.h"#include "private.h"/* * Record keys for keydb */#define SALT_STRING "global-salt"#define VERSION_STRING "Version"#define KEYDB_PW_CHECK_STRING "password-check"#define KEYDB_PW_CHECK_LEN 14/* Size of the global salt for key database */#define SALT_LENGTH 16/* ASN1 Templates for new decoder/encoder *//* * Attribute value for PKCS8 entries (static?) */const SEC_ASN1Template SECKEY_AttributeTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYAttribute) }, { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) }, { SEC_ASN1_SET_OF, offsetof(SECKEYAttribute, attrValue), SEC_AnyTemplate }, { 0 }};const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = { { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate },};const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) }, { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo,version) }, { SEC_ASN1_INLINE, offsetof(SECKEYPrivateKeyInfo,algorithm), SECOID_AlgorithmIDTemplate }, { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo,privateKey) }, { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(SECKEYPrivateKeyInfo,attributes), SECKEY_SetOfAttributeTemplate }, { 0 }};const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = { { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate }};const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) }, { SEC_ASN1_INLINE, offsetof(SECKEYEncryptedPrivateKeyInfo,algorithm), SECOID_AlgorithmIDTemplate }, { SEC_ASN1_OCTET_STRING, offsetof(SECKEYEncryptedPrivateKeyInfo,encryptedData) }, { 0 }};const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = { { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }};/* ====== Default key databse encryption algorithm ====== */static SECOidTag defaultKeyDBAlg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;/* * Default algorithm for encrypting data in the key database */SECOidTagSECKEY_GetDefaultKeyDBAlg(void){ return(defaultKeyDBAlg);}voidSECKEY_SetDefaultKeyDBAlg(SECOidTag alg){ defaultKeyDBAlg = alg; return;}static voidsec_destroy_dbkey(SECKEYDBKey *dbkey){ if ( dbkey && dbkey->arena ) { PORT_FreeArena(dbkey->arena, PR_FALSE); }}static voidfree_dbt(DBT *dbt){ if ( dbt ) { PORT_Free(dbt->data); PORT_Free(dbt); } return;}/* * format of key database entries for version 3 of database: * byte offset field * ----------- ----- * 0 version * 1 salt-len * 2 nn-len * 3.. salt-data * ... nickname * ... encrypted-key-data */static DBT *encode_dbkey(SECKEYDBKey *dbkey){ DBT *bufitem = NULL; unsigned char *buf; int nnlen; char *nn; bufitem = (DBT *)PORT_ZAlloc(sizeof(DBT)); if ( bufitem == NULL ) { goto loser; } if ( dbkey->nickname ) { nn = dbkey->nickname; nnlen = PORT_Strlen(nn) + 1; } else { nn = ""; nnlen = 1; } /* compute the length of the record */ /* 1 + 1 + 1 == version number header + salt length + nn len */ bufitem->size = dbkey->salt.len + nnlen + dbkey->derPK.len + 1 + 1 + 1; bufitem->data = (void *)PORT_ZAlloc(bufitem->size); if ( bufitem->data == NULL ) { goto loser; } buf = (unsigned char *)bufitem->data; /* set version number */ buf[0] = PRIVATE_KEY_DB_FILE_VERSION; /* set length of salt */ PORT_Assert(dbkey->salt.len < 256); buf[1] = dbkey->salt.len; /* set length of nickname */ PORT_Assert(nnlen < 256); buf[2] = nnlen; /* copy salt */ PORT_Memcpy(&buf[3], dbkey->salt.data, dbkey->salt.len); /* copy nickname */ PORT_Memcpy(&buf[3 + dbkey->salt.len], nn, nnlen); /* copy encrypted key */ PORT_Memcpy(&buf[3 + dbkey->salt.len + nnlen], dbkey->derPK.data, dbkey->derPK.len); return(bufitem); loser: if ( bufitem ) { free_dbt(bufitem); } return(NULL);}static SECKEYDBKey *decode_dbkey(DBT *bufitem, int expectedVersion){ SECKEYDBKey *dbkey; PLArenaPool *arena = NULL; unsigned char *buf; int version; int keyoff; int nnlen; int saltoff; buf = (unsigned char *)bufitem->data; version = buf[0]; if ( version != expectedVersion ) { goto loser; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) { goto loser; } dbkey = (SECKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYDBKey)); if ( dbkey == NULL ) { goto loser; } dbkey->arena = arena; dbkey->salt.data = NULL; dbkey->derPK.data = NULL; dbkey->salt.len = buf[1]; dbkey->salt.data = (unsigned char *)PORT_ArenaZAlloc(arena, dbkey->salt.len); if ( dbkey->salt.data == NULL ) { goto loser; } saltoff = 2; keyoff = 2 + dbkey->salt.len; if ( expectedVersion == PRIVATE_KEY_DB_FILE_VERSION ) { nnlen = buf[2]; if ( nnlen ) { dbkey->nickname = (char *)PORT_ArenaZAlloc(arena, nnlen + 1); if ( dbkey->nickname ) { PORT_Memcpy(dbkey->nickname, &buf[keyoff+1], nnlen); } } keyoff += ( nnlen + 1 ); saltoff = 3; } PORT_Memcpy(dbkey->salt.data, &buf[saltoff], dbkey->salt.len); dbkey->derPK.len = bufitem->size - keyoff; dbkey->derPK.data = (unsigned char *)PORT_ArenaZAlloc(arena,dbkey->derPK.len); if ( dbkey->derPK.data == NULL ) { goto loser; } PORT_Memcpy(dbkey->derPK.data, &buf[keyoff], dbkey->derPK.len); return(dbkey); loser: if ( arena ) { PORT_FreeArena(arena, PR_FALSE); } return(NULL);}static SECKEYDBKey *get_dbkey(SECKEYKeyDBHandle *handle, DBT *index){ SECKEYDBKey *dbkey; DBT entry; SECStatus rv; /* get it from the database */ rv = (SECStatus)(* handle->db->get)(handle->db, index, &entry, 0); if ( rv ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return NULL; } /* set up dbkey struct */ dbkey = decode_dbkey(&entry, PRIVATE_KEY_DB_FILE_VERSION); return(dbkey);}static SECStatusput_dbkey(SECKEYKeyDBHandle *handle, DBT *index, SECKEYDBKey *dbkey, PRBool update){ DBT *keydata = NULL; int status; keydata = encode_dbkey(dbkey); if ( keydata == NULL ) { goto loser; } /* put it in the database */ if ( update ) { status = (* handle->db->put)(handle->db, index, keydata, 0); } else { status = (* handle->db->put)(handle->db, index, keydata, R_NOOVERWRITE); } if ( status ) { goto loser; } /* sync the database */ status = (* handle->db->sync)(handle->db, 0); if ( status ) { goto loser; } free_dbt(keydata); return(SECSuccess);loser: if ( keydata ) { free_dbt(keydata); } return(SECFailure);}SECStatusSECKEY_TraverseKeys(SECKEYKeyDBHandle *handle, SECStatus (* keyfunc)(DBT *k, DBT *d, void *pdata), void *udata ){ DBT data; DBT key; SECStatus status; int rv; if (handle == NULL) { return(SECFailure); } rv = (* handle->db->seq)(handle->db, &key, &data, R_FIRST); if ( rv ) { return(SECFailure); } do { /* skip version record */ if ( data.size > 1 ) { if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) { if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) { continue; } } /* skip password check */ if ( key.size == KEYDB_PW_CHECK_LEN ) { if ( PORT_Memcmp(key.data, KEYDB_PW_CHECK_STRING, KEYDB_PW_CHECK_LEN) == 0 ) { continue; } } status = (* keyfunc)(&key, &data, udata); if (status != SECSuccess) { return(status); } } } while ( (* handle->db->seq)(handle->db, &key, &data, R_NEXT) == 0 ); return(SECSuccess);}typedef struct keyNode { struct keyNode *next; DBT key;} keyNode;typedef struct { PLArenaPool *arena; keyNode *head;} keyList;static SECStatussec_add_key_to_list(DBT *key, DBT *data, void *arg){ keyList *keylist; keyNode *node; void *keydata; keylist = (keyList *)arg; /* allocate the node struct */ node = (keyNode*)PORT_ArenaZAlloc(keylist->arena, sizeof(keyNode)); if ( node == NULL ) { return(SECFailure); } /* allocate room for key data */ keydata = PORT_ArenaZAlloc(keylist->arena, key->size); if ( keydata == NULL ) { return(SECFailure); } /* link node into list */ node->next = keylist->head; keylist->head = node; /* copy key into node */ PORT_Memcpy(keydata, key->data, key->size); node->key.size = key->size; node->key.data = keydata; return(SECSuccess);}static SECItem *decodeKeyDBGlobalSalt(DBT *saltData){ SECItem *saltitem; saltitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if ( saltitem == NULL ) { return(NULL); } saltitem->data = (unsigned char *)PORT_ZAlloc(saltData->size); if ( saltitem->data == NULL ) { PORT_Free(saltitem); return(NULL); } saltitem->len = saltData->size; PORT_Memcpy(saltitem->data, saltData->data, saltitem->len); return(saltitem);}static SECItem *GetKeyDBGlobalSalt(SECKEYKeyDBHandle *handle){ DBT saltKey; DBT saltData; int ret; saltKey.data = SALT_STRING; saltKey.size = sizeof(SALT_STRING) - 1; ret = (* handle->db->get)(handle->db, &saltKey, &saltData, 0); if ( ret ) { return(NULL); } return(decodeKeyDBGlobalSalt(&saltData));}static SECStatusmakeGlobalVersion(SECKEYKeyDBHandle *handle){ unsigned char version; DBT versionData; DBT versionKey; int status; version = PRIVATE_KEY_DB_FILE_VERSION; versionData.data = &version; versionData.size = 1; versionKey.data = VERSION_STRING; versionKey.size = sizeof(VERSION_STRING)-1; /* put version string into the database now */ status = (* handle->db->put)(handle->db, &versionKey, &versionData, 0); if ( status ) { return(SECFailure); } return(SECSuccess);}static SECStatusmakeGlobalSalt(SECKEYKeyDBHandle *handle){ DBT saltKey; DBT saltData; unsigned char saltbuf[16]; int status; saltKey.data = SALT_STRING; saltKey.size = sizeof(SALT_STRING) - 1; saltData.data = (void *)saltbuf; saltData.size = sizeof(saltbuf); RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf)); /* put global salt into the database now */ status = (* handle->db->put)( handle->db, &saltKey, &saltData, 0); if ( status ) { return(SECFailure); } return(SECSuccess);}static char *keyDBFilenameCallback(void *arg, int dbVersion){ return(PORT_Strdup((char *)arg));}SECKEYKeyDBHandle *SECKEY_OpenKeyDBFilename(char *dbname, PRBool readOnly){ return(SECKEY_OpenKeyDB(readOnly, keyDBFilenameCallback, (void *)dbname));}SECKEYKeyDBHandle *SECKEY_OpenKeyDB(PRBool readOnly, SECKEYDBNameFunc namecb, void *cbarg){ SECKEYKeyDBHandle *handle; DBT versionKey; DBT versionData; int rv; int openflags; char *dbname = NULL; PRBool updated = PR_FALSE; handle = (SECKEYKeyDBHandle *)PORT_ZAlloc (sizeof(SECKEYKeyDBHandle)); if (handle == NULL) { PORT_SetError (SEC_ERROR_NO_MEMORY); return NULL; } versionKey.data = VERSION_STRING; versionKey.size = sizeof(VERSION_STRING)-1; if ( readOnly ) { openflags = O_RDONLY;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?