mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-02 13:27:33 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
399
security/nss/lib/softoken/legacydb/lgutil.c
Normal file
399
security/nss/lib/softoken/legacydb/lgutil.c
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "lgdb.h"
|
||||
#include "secerr.h"
|
||||
#include "lgglue.h"
|
||||
|
||||
/*
|
||||
* ******************** Attribute Utilities *******************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* look up and attribute structure from a type and Object structure.
|
||||
* The returned attribute is referenced and needs to be freed when
|
||||
* it is no longer needed.
|
||||
*/
|
||||
const CK_ATTRIBUTE *
|
||||
lg_FindAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (templ[i].type == type) {
|
||||
return &templ[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* return true if object has attribute
|
||||
*/
|
||||
PRBool
|
||||
lg_hasAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count)
|
||||
{
|
||||
if (lg_FindAttribute(type, templ, count) == NULL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an attribute into a SECItem. Secitem is allocated in the specified
|
||||
* arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_Attribute2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item)
|
||||
{
|
||||
int len;
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL)
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
len = attribute->ulValueLen;
|
||||
|
||||
if (arena) {
|
||||
item->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
|
||||
} else {
|
||||
item->data = (unsigned char *)PORT_Alloc(len);
|
||||
}
|
||||
if (item->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
item->len = len;
|
||||
if (item->len) {
|
||||
PORT_Memcpy(item->data, attribute->pValue, len);
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an unsigned attribute into a SECItem. Secitem is allocated in
|
||||
* the specified arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_Attribute2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
item->data = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL)
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
(void)SECITEM_AllocItem(arena, item, attribute->ulValueLen);
|
||||
if (item->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
PORT_Memcpy(item->data, attribute->pValue, item->len);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an unsigned attribute into a SECItem. Secitem is allocated in
|
||||
* the specified arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_PrivAttr2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
SECItem epki, *dest = NULL;
|
||||
SECStatus rv;
|
||||
|
||||
item->data = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL)
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
epki.data = attribute->pValue;
|
||||
epki.len = attribute->ulValueLen;
|
||||
|
||||
rv = lg_util_decrypt(sdbpw, &epki, &dest);
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_USER_NOT_LOGGED_IN;
|
||||
}
|
||||
(void)SECITEM_AllocItem(arena, item, dest->len);
|
||||
if (item->data == NULL) {
|
||||
SECITEM_FreeItem(dest, PR_TRUE);
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
|
||||
PORT_Memcpy(item->data, dest->data, item->len);
|
||||
SECITEM_FreeItem(dest, PR_TRUE);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_PrivAttr2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw)
|
||||
{
|
||||
return lg_PrivAttr2SSecItem(arena, type, templ, count, item, sdbpw);
|
||||
}
|
||||
|
||||
/*
|
||||
* this is only valid for CK_BBOOL type attributes. Return the state
|
||||
* of that attribute.
|
||||
*/
|
||||
PRBool
|
||||
lg_isTrue(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
PRBool tok = PR_FALSE;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
tok = (PRBool)(*(CK_BBOOL *)attribute->pValue);
|
||||
|
||||
return tok;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a null terminated string from attribute 'type'. This string
|
||||
* is allocated and needs to be freed with PORT_Free() When complete.
|
||||
*/
|
||||
char *
|
||||
lg_getString(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
char *label = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL)
|
||||
return NULL;
|
||||
|
||||
if (attribute->pValue != NULL) {
|
||||
label = (char *)PORT_Alloc(attribute->ulValueLen + 1);
|
||||
if (label == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PORT_Memcpy(label, attribute->pValue, attribute->ulValueLen);
|
||||
label[attribute->ulValueLen] = 0;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count, CK_ULONG *longData)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
CK_ULONG value = 0;
|
||||
const unsigned char *data;
|
||||
int i;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL)
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
if (attribute->ulValueLen != 4) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
data = (const unsigned char *)attribute->pValue;
|
||||
for (i = 0; i < 4; i++) {
|
||||
value |= (CK_ULONG)(data[i]) << ((3 - i) * 8);
|
||||
}
|
||||
|
||||
*longData = value;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************** Object Utilities *******************************
|
||||
*/
|
||||
|
||||
SECStatus
|
||||
lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
SECItem *item;
|
||||
PRBool rem;
|
||||
PLHashTable *hashTable = lg_GetHashTable(sdb);
|
||||
|
||||
item = (SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
|
||||
rem = PL_HashTableRemove(hashTable, (void *)handle);
|
||||
if (rem && item) {
|
||||
SECITEM_FreeItem(item, PR_TRUE);
|
||||
}
|
||||
return rem ? SECSuccess : SECFailure;
|
||||
}
|
||||
|
||||
/* must be called holding lg_DBLock(sdb) */
|
||||
static SECStatus
|
||||
lg_addTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle, SECItem *key)
|
||||
{
|
||||
PLHashEntry *entry;
|
||||
SECItem *item;
|
||||
PLHashTable *hashTable = lg_GetHashTable(sdb);
|
||||
|
||||
item = SECITEM_DupItem(key);
|
||||
if (item == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
entry = PL_HashTableAdd(hashTable, (void *)handle, item);
|
||||
if (entry == NULL) {
|
||||
SECITEM_FreeItem(item, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* must be called holding lg_DBLock(sdb) */
|
||||
const SECItem *
|
||||
lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
PLHashTable *hashTable = lg_GetHashTable(sdb);
|
||||
return (const SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
lg_freeHashItem(PLHashEntry *entry, PRIntn index, void *arg)
|
||||
{
|
||||
SECItem *item = (SECItem *)entry->value;
|
||||
|
||||
SECITEM_FreeItem(item, PR_TRUE);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_ClearTokenKeyHashTable(SDB *sdb)
|
||||
{
|
||||
PLHashTable *hashTable;
|
||||
lg_DBLock(sdb);
|
||||
hashTable = lg_GetHashTable(sdb);
|
||||
PL_HashTableEnumerateEntries(hashTable, lg_freeHashItem, NULL);
|
||||
lg_DBUnlock(sdb);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle Token Object stuff
|
||||
*/
|
||||
static void
|
||||
lg_XORHash(unsigned char *key, unsigned char *dbkey, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
PORT_Memset(key, 0, 4);
|
||||
|
||||
for (i = 0; i < len - 4; i += 4) {
|
||||
key[0] ^= dbkey[i];
|
||||
key[1] ^= dbkey[i + 1];
|
||||
key[2] ^= dbkey[i + 2];
|
||||
key[3] ^= dbkey[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a token handle for an object and record it so we can find it again */
|
||||
CK_OBJECT_HANDLE
|
||||
lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
|
||||
{
|
||||
unsigned char hashBuf[4];
|
||||
CK_OBJECT_HANDLE handle;
|
||||
const SECItem *key;
|
||||
|
||||
handle = class;
|
||||
/* there is only one KRL, use a fixed handle for it */
|
||||
if (handle != LG_TOKEN_KRL_HANDLE) {
|
||||
lg_XORHash(hashBuf, dbKey->data, dbKey->len);
|
||||
handle = ((CK_OBJECT_HANDLE)hashBuf[0] << 24) |
|
||||
((CK_OBJECT_HANDLE)hashBuf[1] << 16) |
|
||||
((CK_OBJECT_HANDLE)hashBuf[2] << 8) |
|
||||
(CK_OBJECT_HANDLE)hashBuf[3];
|
||||
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK | LG_TOKEN_MASK));
|
||||
/* we have a CRL who's handle has randomly matched the reserved KRL
|
||||
* handle, increment it */
|
||||
if (handle == LG_TOKEN_KRL_HANDLE) {
|
||||
handle++;
|
||||
}
|
||||
}
|
||||
|
||||
lg_DBLock(sdb);
|
||||
while ((key = lg_lookupTokenKeyByHandle(sdb, handle)) != NULL) {
|
||||
if (SECITEM_ItemsAreEqual(key, dbKey)) {
|
||||
lg_DBUnlock(sdb);
|
||||
return handle;
|
||||
}
|
||||
handle++;
|
||||
}
|
||||
lg_addTokenKeyByHandle(sdb, handle, dbKey);
|
||||
lg_DBUnlock(sdb);
|
||||
return handle;
|
||||
}
|
||||
|
||||
PRBool
|
||||
lg_poisonHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
|
||||
{
|
||||
unsigned char hashBuf[4];
|
||||
CK_OBJECT_HANDLE handle;
|
||||
const SECItem *key;
|
||||
|
||||
handle = class;
|
||||
/* there is only one KRL, use a fixed handle for it */
|
||||
if (handle != LG_TOKEN_KRL_HANDLE) {
|
||||
lg_XORHash(hashBuf, dbKey->data, dbKey->len);
|
||||
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
|
||||
(hashBuf[2] << 8) | hashBuf[3];
|
||||
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK | LG_TOKEN_MASK));
|
||||
/* we have a CRL who's handle has randomly matched the reserved KRL
|
||||
* handle, increment it */
|
||||
if (handle == LG_TOKEN_KRL_HANDLE) {
|
||||
handle++;
|
||||
}
|
||||
}
|
||||
lg_DBLock(sdb);
|
||||
while ((key = lg_lookupTokenKeyByHandle(sdb, handle)) != NULL) {
|
||||
if (SECITEM_ItemsAreEqual(key, dbKey)) {
|
||||
key->data[0] ^= 0x80;
|
||||
lg_DBUnlock(sdb);
|
||||
return PR_TRUE;
|
||||
}
|
||||
handle++;
|
||||
}
|
||||
lg_DBUnlock(sdb);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static LGEncryptFunc lg_encrypt_stub = NULL;
|
||||
static LGDecryptFunc lg_decrypt_stub = NULL;
|
||||
|
||||
void
|
||||
legacy_SetCryptFunctions(LGEncryptFunc enc, LGDecryptFunc dec)
|
||||
{
|
||||
lg_encrypt_stub = enc;
|
||||
lg_decrypt_stub = dec;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
lg_util_encrypt(PLArenaPool *arena, SDB *sdb,
|
||||
SECItem *plainText, SECItem **cipherText)
|
||||
{
|
||||
if (lg_encrypt_stub == NULL) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*lg_encrypt_stub)(arena, sdb, plainText, cipherText);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
lg_util_decrypt(SDB *sdb, SECItem *cipherText, SECItem **plainText)
|
||||
{
|
||||
if (lg_decrypt_stub == NULL) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*lg_decrypt_stub)(sdb, cipherText, plainText);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue