security/nss/lib/softoken/legacydb/lgutil.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 #include "lgdb.h"
     5 #include "secerr.h"
     6 #include "lgglue.h"
     8 /*
     9  * ******************** Attribute Utilities *******************************
    10  */
    12 /*
    13  * look up and attribute structure from a type and Object structure.
    14  * The returned attribute is referenced and needs to be freed when 
    15  * it is no longer needed.
    16  */
    17 const CK_ATTRIBUTE *
    18 lg_FindAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
    19 		 CK_ULONG count )
    20 {
    21     unsigned int i;
    23     for (i=0; i < count; i++) {
    24 	if (templ[i].type == type) {
    25 	    return &templ[i];
    26 	}
    27     }
    28     return NULL;
    29 }
    32 /*
    33  * return true if object has attribute
    34  */
    35 PRBool
    36 lg_hasAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
    37 		 CK_ULONG count )
    38 {
    39    if (lg_FindAttribute(type, templ, count) == NULL) {
    40 	return PR_FALSE;
    41    }
    42    return PR_TRUE;
    43 }
    45 /* 
    46  * copy an attribute into a SECItem. Secitem is allocated in the specified
    47  * arena.
    48  */
    49 CK_RV
    50 lg_Attribute2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
    51 			const CK_ATTRIBUTE *templ, CK_ULONG count,
    52 			SECItem *item)
    53 {
    54     int len;
    55     const CK_ATTRIBUTE *attribute;
    57     attribute = lg_FindAttribute(type, templ, count);
    58     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
    59     len = attribute->ulValueLen;
    61     if (arena) {
    62     	item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
    63     } else {
    64     	item->data = (unsigned char *) PORT_Alloc(len);
    65     }
    66     if (item->data == NULL) {
    67 	return CKR_HOST_MEMORY;
    68     }
    69     item->len = len;
    70     PORT_Memcpy(item->data, attribute->pValue, len);
    71     return CKR_OK;
    72 }
    75 /* 
    76  * copy an unsigned attribute into a SECItem. Secitem is allocated in
    77  * the specified arena.
    78  */
    79 CK_RV
    80 lg_Attribute2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
    81 			const CK_ATTRIBUTE *templ, CK_ULONG count,
    82 			SECItem *item)
    83 {
    84     const CK_ATTRIBUTE *attribute;
    85     item->data = NULL;
    87     attribute = lg_FindAttribute(type, templ, count);
    88     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
    90     (void)SECITEM_AllocItem(arena, item, attribute->ulValueLen);
    91     if (item->data == NULL) {
    92 	return CKR_HOST_MEMORY;
    93     }
    94     PORT_Memcpy(item->data, attribute->pValue, item->len);
    95     return CKR_OK;
    96 }
    98 /* 
    99  * copy an unsigned attribute into a SECItem. Secitem is allocated in
   100  * the specified arena.
   101  */
   102 CK_RV
   103 lg_PrivAttr2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
   104 			const CK_ATTRIBUTE *templ, CK_ULONG count,
   105 			SECItem *item, SDB *sdbpw)
   106 {
   107     const CK_ATTRIBUTE *attribute;
   108     SECItem epki, *dest = NULL;
   109     SECStatus rv;
   111     item->data = NULL;
   113     attribute = lg_FindAttribute(type, templ, count);
   114     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
   116     epki.data = attribute->pValue;
   117     epki.len = attribute->ulValueLen;
   119     rv = lg_util_decrypt(sdbpw, &epki, &dest);
   120     if (rv != SECSuccess) {
   121 	return CKR_USER_NOT_LOGGED_IN;
   122     }
   123     (void)SECITEM_AllocItem(arena, item, dest->len);
   124     if (item->data == NULL) {
   125 	SECITEM_FreeItem(dest, PR_TRUE);
   126 	return CKR_HOST_MEMORY;
   127     }
   129     PORT_Memcpy(item->data, dest->data, item->len);
   130     SECITEM_FreeItem(dest, PR_TRUE);
   131     return CKR_OK;
   132 }
   134 CK_RV
   135 lg_PrivAttr2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
   136 			const CK_ATTRIBUTE *templ, CK_ULONG count,
   137 			SECItem *item, SDB *sdbpw)
   138 {
   139     return lg_PrivAttr2SSecItem(arena, type, templ, count, item, sdbpw);
   140 }
   142 /*
   143  * this is only valid for CK_BBOOL type attributes. Return the state
   144  * of that attribute.
   145  */
   146 PRBool
   147 lg_isTrue(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
   148 {
   149     const CK_ATTRIBUTE *attribute;
   150     PRBool tok = PR_FALSE;
   152     attribute=lg_FindAttribute(type, templ, count);
   153     if (attribute == NULL) { return PR_FALSE; }
   154     tok = (PRBool)(*(CK_BBOOL *)attribute->pValue);
   156     return tok;
   157 }
   159 /*
   160  * return a null terminated string from attribute 'type'. This string
   161  * is allocated and needs to be freed with PORT_Free() When complete.
   162  */
   163 char *
   164 lg_getString(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
   165 {
   166     const CK_ATTRIBUTE *attribute;
   167     char *label = NULL;
   169     attribute = lg_FindAttribute(type, templ, count);
   170     if (attribute == NULL) return NULL;
   172     if (attribute->pValue != NULL) {
   173 	label = (char *) PORT_Alloc(attribute->ulValueLen+1);
   174 	if (label == NULL) {
   175 	    return NULL;
   176 	}
   178 	PORT_Memcpy(label,attribute->pValue, attribute->ulValueLen);
   179 	label[attribute->ulValueLen] = 0;
   180     }
   181     return label;
   182 }
   184 CK_RV
   185 lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
   186 				 CK_ULONG count, CK_ULONG *longData)
   187 {
   188     const CK_ATTRIBUTE *attribute;
   189     CK_ULONG value = 0;
   190     const unsigned char *data;
   191     int i;
   193     attribute = lg_FindAttribute(type, templ, count);
   194     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
   196     if (attribute->ulValueLen != 4) {
   197 	return CKR_ATTRIBUTE_VALUE_INVALID;
   198     }
   199     data = (const unsigned char *)attribute->pValue;
   200     for (i=0; i < 4; i++) {
   201 	value |= (CK_ULONG)(data[i]) << ((3-i)*8);
   202     }
   204     *longData = value;
   205     return CKR_OK;
   206 }
   208 /*
   209  * ******************** Object Utilities *******************************
   210  */
   212 SECStatus
   213 lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
   214 {
   215     SECItem *item;
   216     PRBool rem;
   217     PLHashTable *hashTable= lg_GetHashTable(sdb);
   219     item = (SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
   220     rem = PL_HashTableRemove(hashTable,(void *)handle) ;
   221     if (rem && item) {
   222 	SECITEM_FreeItem(item,PR_TRUE);
   223     }
   224     return rem ? SECSuccess : SECFailure;
   225 }
   227 /* must be called holding lg_DBLock(sdb) */
   228 static SECStatus
   229 lg_addTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle, SECItem *key)
   230 {
   231     PLHashEntry *entry;
   232     SECItem *item;
   233     PLHashTable *hashTable= lg_GetHashTable(sdb);
   235     item = SECITEM_DupItem(key);
   236     if (item == NULL) {
   237 	return SECFailure;
   238     }
   239     entry = PL_HashTableAdd(hashTable,(void *)handle,item);
   240     if (entry == NULL) {
   241 	SECITEM_FreeItem(item,PR_TRUE);
   242 	return SECFailure;
   243     }
   244     return SECSuccess;
   245 }
   247 /* must be called holding lg_DBLock(sdb) */
   248 const SECItem *
   249 lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
   250 {
   251     PLHashTable *hashTable= lg_GetHashTable(sdb);
   252     return (const SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
   253 }
   256 static PRIntn
   257 lg_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
   258 {
   259     SECItem *item = (SECItem *)entry->value;
   261     SECITEM_FreeItem(item, PR_TRUE);
   262     return HT_ENUMERATE_NEXT;
   263 }
   265 CK_RV
   266 lg_ClearTokenKeyHashTable(SDB *sdb)
   267 {
   268     PLHashTable *hashTable;
   269     lg_DBLock(sdb);
   270     hashTable= lg_GetHashTable(sdb);
   271     PL_HashTableEnumerateEntries(hashTable, lg_freeHashItem, NULL);
   272     lg_DBUnlock(sdb);
   273     return CKR_OK;
   274 }
   276 /*
   277  * handle Token Object stuff
   278  */
   279 static void
   280 lg_XORHash(unsigned char *key, unsigned char *dbkey, int len)
   281 {
   282    int i;
   284    PORT_Memset(key, 0, 4);
   286    for (i=0; i < len-4; i += 4) {
   287 	key[0] ^= dbkey[i];
   288 	key[1] ^= dbkey[i+1];
   289 	key[2] ^= dbkey[i+2];
   290 	key[3] ^= dbkey[i+3];
   291    }
   292 }
   294 /* Make a token handle for an object and record it so we can find it again */
   295 CK_OBJECT_HANDLE
   296 lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
   297 {
   298     unsigned char hashBuf[4];
   299     CK_OBJECT_HANDLE handle;
   300     const SECItem *key;
   302     handle = class;
   303     /* there is only one KRL, use a fixed handle for it */
   304     if (handle != LG_TOKEN_KRL_HANDLE) {
   305 	lg_XORHash(hashBuf,dbKey->data,dbKey->len);
   306 	handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | 
   307 					(hashBuf[2] << 8)  | hashBuf[3];
   308 	handle =  class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
   309 	/* we have a CRL who's handle has randomly matched the reserved KRL
   310 	 * handle, increment it */
   311 	if (handle == LG_TOKEN_KRL_HANDLE) {
   312 	    handle++;
   313 	}
   314     }
   316     lg_DBLock(sdb);
   317     while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
   318 	if (SECITEM_ItemsAreEqual(key,dbKey)) {
   319     	   lg_DBUnlock(sdb);
   320 	   return handle;
   321 	}
   322 	handle++;
   323     }
   324     lg_addTokenKeyByHandle(sdb,handle,dbKey);
   325     lg_DBUnlock(sdb);
   326     return handle;
   327 }
   329 PRBool
   330 lg_poisonHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
   331 {
   332     unsigned char hashBuf[4];
   333     CK_OBJECT_HANDLE handle;
   334     const SECItem *key;
   336     handle = class;
   337     /* there is only one KRL, use a fixed handle for it */
   338     if (handle != LG_TOKEN_KRL_HANDLE) {
   339 	lg_XORHash(hashBuf,dbKey->data,dbKey->len);
   340 	handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | 
   341 					(hashBuf[2] << 8)  | hashBuf[3];
   342 	handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
   343 	/* we have a CRL who's handle has randomly matched the reserved KRL
   344 	 * handle, increment it */
   345 	if (handle == LG_TOKEN_KRL_HANDLE) {
   346 	    handle++;
   347 	}
   348     }
   349     lg_DBLock(sdb);
   350     while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
   351 	if (SECITEM_ItemsAreEqual(key,dbKey)) {
   352 	   key->data[0] ^= 0x80;
   353     	   lg_DBUnlock(sdb);
   354 	   return PR_TRUE;
   355 	}
   356 	handle++;
   357     }
   358     lg_DBUnlock(sdb);
   359     return PR_FALSE;
   360 }
   362 static LGEncryptFunc lg_encrypt_stub = NULL;
   363 static LGDecryptFunc lg_decrypt_stub = NULL;
   365 void
   366 legacy_SetCryptFunctions(LGEncryptFunc enc, LGDecryptFunc dec)
   367 {
   368    lg_encrypt_stub = enc;
   369    lg_decrypt_stub = dec;
   370 }
   372 SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdb, 
   373 			  SECItem *plainText, SECItem **cipherText)
   374 {
   375     if (lg_encrypt_stub == NULL) {
   376 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   377 	return SECFailure;
   378     }
   379     return (*lg_encrypt_stub)(arena, sdb, plainText, cipherText);
   380 }
   382 SECStatus lg_util_decrypt(SDB *sdb, SECItem *cipherText, SECItem **plainText)
   383 {
   384     if (lg_decrypt_stub == NULL) {
   385 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   386 	return SECFailure;
   387     }
   388     return (*lg_decrypt_stub)(sdb, cipherText, plainText);
   389 }

mercurial