diff options
Diffstat (limited to 'nss/lib/pk11wrap/pk11sdr.c')
-rw-r--r-- | nss/lib/pk11wrap/pk11sdr.c | 570 |
1 files changed, 315 insertions, 255 deletions
diff --git a/nss/lib/pk11wrap/pk11sdr.c b/nss/lib/pk11wrap/pk11sdr.c index 43030b6..eb67bfb 100644 --- a/nss/lib/pk11wrap/pk11sdr.c +++ b/nss/lib/pk11wrap/pk11sdr.c @@ -13,34 +13,33 @@ * Data structure and template for encoding the result of an SDR operation * This is temporary. It should include the algorithm ID of the encryption mechanism */ -struct SDRResult -{ - SECItem keyid; - SECAlgorithmID alg; - SECItem data; +struct SDRResult { + SECItem keyid; + SECAlgorithmID alg; + SECItem data; }; typedef struct SDRResult SDRResult; SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) static SEC_ASN1Template template[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (SDRResult) }, - { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SDRResult, alg), - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, - { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) }, - { 0 } + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SDRResult) }, + { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SDRResult, alg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) }, + { 0 } }; static unsigned char keyID[] = { - 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; static SECItem keyIDItem = { - 0, - keyID, - sizeof keyID + 0, + keyID, + sizeof keyID }; /* local utility function for padding an incoming data block @@ -49,82 +48,91 @@ static SECItem keyIDItem = { static SECStatus padBlock(SECItem *data, int blockSize, SECItem *result) { - SECStatus rv = SECSuccess; - int padLength; - unsigned int i; + SECStatus rv = SECSuccess; + int padLength; + unsigned int i; - result->data = 0; - result->len = 0; + result->data = 0; + result->len = 0; - /* This algorithm always adds to the block (to indicate the number + /* This algorithm always adds to the block (to indicate the number * of pad bytes). So allocate a block large enough. */ - padLength = blockSize - (data->len % blockSize); - result->len = data->len + padLength; - result->data = (unsigned char *)PORT_Alloc(result->len); + padLength = blockSize - (data->len % blockSize); + result->len = data->len + padLength; + result->data = (unsigned char *)PORT_Alloc(result->len); - /* Copy the data */ - PORT_Memcpy(result->data, data->data, data->len); + /* Copy the data */ + PORT_Memcpy(result->data, data->data, data->len); - /* Add the pad values */ - for(i = data->len; i < result->len; i++) - result->data[i] = (unsigned char)padLength; + /* Add the pad values */ + for (i = data->len; i < result->len; i++) + result->data[i] = (unsigned char)padLength; - return rv; + return rv; } static SECStatus unpadBlock(SECItem *data, int blockSize, SECItem *result) { - SECStatus rv = SECSuccess; - int padLength; - unsigned int i; + SECStatus rv = SECSuccess; + int padLength; + unsigned int i; - result->data = 0; - result->len = 0; + result->data = 0; + result->len = 0; - /* Remove the padding from the end if the input data */ - if (data->len == 0 || data->len % blockSize != 0) { rv = SECFailure; goto loser; } + /* Remove the padding from the end if the input data */ + if (data->len == 0 || data->len % blockSize != 0) { + rv = SECFailure; + goto loser; + } - padLength = data->data[data->len-1]; - if (padLength > blockSize) { rv = SECFailure; goto loser; } + padLength = data->data[data->len - 1]; + if (padLength > blockSize) { + rv = SECFailure; + goto loser; + } - /* verify padding */ - for (i=data->len - padLength; i < data->len; i++) { - if (data->data[i] != padLength) { - rv = SECFailure; - goto loser; + /* verify padding */ + for (i = data->len - padLength; i < data->len; i++) { + if (data->data[i] != padLength) { + rv = SECFailure; + goto loser; + } } - } - result->len = data->len - padLength; - result->data = (unsigned char *)PORT_Alloc(result->len); - if (!result->data) { rv = SECFailure; goto loser; } + result->len = data->len - padLength; + result->data = (unsigned char *)PORT_Alloc(result->len); + if (!result->data) { + rv = SECFailure; + goto loser; + } - PORT_Memcpy(result->data, data->data, result->len); + PORT_Memcpy(result->data, data->data, result->len); - if (padLength < 2) { - return SECWouldBlock; - } + if (padLength < 2) { + return SECWouldBlock; + } loser: - return rv; + return rv; } static PRLock *pk11sdrLock = NULL; void -pk11sdr_Init (void) +pk11sdr_Init(void) { - pk11sdrLock = PR_NewLock(); + pk11sdrLock = PR_NewLock(); } void pk11sdr_Shutdown(void) { if (pk11sdrLock) { - PR_DestroyLock(pk11sdrLock); - pk11sdrLock = NULL; + PR_DestroyLock(pk11sdrLock); + pk11sdrLock = NULL; } } @@ -136,135 +144,171 @@ pk11sdr_Shutdown(void) SECStatus PK11SDR_Encrypt(SECItem *keyid, SECItem *data, SECItem *result, void *cx) { - SECStatus rv = SECSuccess; - PK11SlotInfo *slot = 0; - PK11SymKey *key = 0; - SECItem *params = 0; - PK11Context *ctx = 0; - CK_MECHANISM_TYPE type; - SDRResult sdrResult; - SECItem paddedData; - SECItem *pKeyID; - PLArenaPool *arena = 0; - - /* Initialize */ - paddedData.len = 0; - paddedData.data = 0; - - arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if (!arena) { rv = SECFailure; goto loser; } - - /* 1. Locate the requested keyid, or the default key (which has a keyid) - * 2. Create an encryption context - * 3. Encrypt - * 4. Encode the results (using ASN.1) - */ - - slot = PK11_GetInternalKeySlot(); - if (!slot) { rv = SECFailure; goto loser; } - - /* Use triple-DES */ - type = CKM_DES3_CBC; - - /* - * Login to the internal token before we look for the key, otherwise we - * won't find it. - */ - rv = PK11_Authenticate(slot, PR_TRUE, cx); - if (rv != SECSuccess) goto loser; - - /* Find the key to use */ - pKeyID = keyid; - if (pKeyID->len == 0) { - pKeyID = &keyIDItem; /* Use default value */ + SECStatus rv = SECSuccess; + PK11SlotInfo *slot = 0; + PK11SymKey *key = 0; + SECItem *params = 0; + PK11Context *ctx = 0; + CK_MECHANISM_TYPE type; + SDRResult sdrResult; + SECItem paddedData; + SECItem *pKeyID; + PLArenaPool *arena = 0; + + /* Initialize */ + paddedData.len = 0; + paddedData.data = 0; + + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (!arena) { + rv = SECFailure; + goto loser; + } - /* put in a course lock to prevent a race between not finding the - * key and creating one. - */ + /* 1. Locate the requested keyid, or the default key (which has a keyid) + * 2. Create an encryption context + * 3. Encrypt + * 4. Encode the results (using ASN.1) + */ - if (pk11sdrLock) PR_Lock(pk11sdrLock); + slot = PK11_GetInternalKeySlot(); + if (!slot) { + rv = SECFailure; + goto loser; + } - /* Try to find the key */ - key = PK11_FindFixedKey(slot, type, pKeyID, cx); - - /* If the default key doesn't exist yet, try to create it */ - if (!key) key = PK11_GenDES3TokenKey(slot, pKeyID, cx); - if (pk11sdrLock) PR_Unlock(pk11sdrLock); - } else { - key = PK11_FindFixedKey(slot, type, pKeyID, cx); - } + /* Use triple-DES */ + type = CKM_DES3_CBC; + + /* + * Login to the internal token before we look for the key, otherwise we + * won't find it. + */ + rv = PK11_Authenticate(slot, PR_TRUE, cx); + if (rv != SECSuccess) + goto loser; + + /* Find the key to use */ + pKeyID = keyid; + if (pKeyID->len == 0) { + pKeyID = &keyIDItem; /* Use default value */ + + /* put in a course lock to prevent a race between not finding the + * key and creating one. + */ + + if (pk11sdrLock) + PR_Lock(pk11sdrLock); + + /* Try to find the key */ + key = PK11_FindFixedKey(slot, type, pKeyID, cx); + + /* If the default key doesn't exist yet, try to create it */ + if (!key) + key = PK11_GenDES3TokenKey(slot, pKeyID, cx); + if (pk11sdrLock) + PR_Unlock(pk11sdrLock); + } else { + key = PK11_FindFixedKey(slot, type, pKeyID, cx); + } - if (!key) { rv = SECFailure; goto loser; } + if (!key) { + rv = SECFailure; + goto loser; + } - params = PK11_GenerateNewParam(type, key); - if (!params) { rv = SECFailure; goto loser; } + params = PK11_GenerateNewParam(type, key); + if (!params) { + rv = SECFailure; + goto loser; + } - ctx = PK11_CreateContextBySymKey(type, CKA_ENCRYPT, key, params); - if (!ctx) { rv = SECFailure; goto loser; } + ctx = PK11_CreateContextBySymKey(type, CKA_ENCRYPT, key, params); + if (!ctx) { + rv = SECFailure; + goto loser; + } - rv = padBlock(data, PK11_GetBlockSize(type, 0), &paddedData); - if (rv != SECSuccess) goto loser; + rv = padBlock(data, PK11_GetBlockSize(type, 0), &paddedData); + if (rv != SECSuccess) + goto loser; - sdrResult.data.len = paddedData.len; - sdrResult.data.data = (unsigned char *)PORT_ArenaAlloc(arena, sdrResult.data.len); + sdrResult.data.len = paddedData.len; + sdrResult.data.data = (unsigned char *)PORT_ArenaAlloc(arena, sdrResult.data.len); - rv = PK11_CipherOp(ctx, sdrResult.data.data, (int*)&sdrResult.data.len, sdrResult.data.len, - paddedData.data, paddedData.len); - if (rv != SECSuccess) goto loser; + rv = PK11_CipherOp(ctx, sdrResult.data.data, (int *)&sdrResult.data.len, sdrResult.data.len, + paddedData.data, paddedData.len); + if (rv != SECSuccess) + goto loser; - PK11_Finalize(ctx); + PK11_Finalize(ctx); - sdrResult.keyid = *pKeyID; + sdrResult.keyid = *pKeyID; - rv = PK11_ParamToAlgid(SEC_OID_DES_EDE3_CBC, params, arena, &sdrResult.alg); - if (rv != SECSuccess) goto loser; + rv = PK11_ParamToAlgid(SEC_OID_DES_EDE3_CBC, params, arena, &sdrResult.alg); + if (rv != SECSuccess) + goto loser; - if (!SEC_ASN1EncodeItem(0, result, &sdrResult, template)) { rv = SECFailure; goto loser; } + if (!SEC_ASN1EncodeItem(0, result, &sdrResult, template)) { + rv = SECFailure; + goto loser; + } loser: - SECITEM_ZfreeItem(&paddedData, PR_FALSE); - if (arena) PORT_FreeArena(arena, PR_TRUE); - if (ctx) PK11_DestroyContext(ctx, PR_TRUE); - if (params) SECITEM_ZfreeItem(params, PR_TRUE); - if (key) PK11_FreeSymKey(key); - if (slot) PK11_FreeSlot(slot); - - return rv; + SECITEM_ZfreeItem(&paddedData, PR_FALSE); + if (arena) + PORT_FreeArena(arena, PR_TRUE); + if (ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if (params) + SECITEM_ZfreeItem(params, PR_TRUE); + if (key) + PK11_FreeSymKey(key); + if (slot) + PK11_FreeSlot(slot); + + return rv; } /* decrypt a block */ static SECStatus -pk11Decrypt(PK11SlotInfo *slot, PLArenaPool *arena, - CK_MECHANISM_TYPE type, PK11SymKey *key, - SECItem *params, SECItem *in, SECItem *result) +pk11Decrypt(PK11SlotInfo *slot, PLArenaPool *arena, + CK_MECHANISM_TYPE type, PK11SymKey *key, + SECItem *params, SECItem *in, SECItem *result) { - PK11Context *ctx = 0; - SECItem paddedResult; - SECStatus rv; + PK11Context *ctx = 0; + SECItem paddedResult; + SECStatus rv; - paddedResult.len = 0; - paddedResult.data = 0; + paddedResult.len = 0; + paddedResult.data = 0; - ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params); - if (!ctx) { rv = SECFailure; goto loser; } + ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params); + if (!ctx) { + rv = SECFailure; + goto loser; + } - paddedResult.len = in->len; - paddedResult.data = PORT_ArenaAlloc(arena, paddedResult.len); + paddedResult.len = in->len; + paddedResult.data = PORT_ArenaAlloc(arena, paddedResult.len); - rv = PK11_CipherOp(ctx, paddedResult.data, - (int*)&paddedResult.len, paddedResult.len, - in->data, in->len); - if (rv != SECSuccess) goto loser; + rv = PK11_CipherOp(ctx, paddedResult.data, + (int *)&paddedResult.len, paddedResult.len, + in->data, in->len); + if (rv != SECSuccess) + goto loser; - PK11_Finalize(ctx); + PK11_Finalize(ctx); - /* Remove the padding */ - rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result); - if (rv) goto loser; + /* Remove the padding */ + rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result); + if (rv) + goto loser; loser: - if (ctx) PK11_DestroyContext(ctx, PR_TRUE); - return rv; + if (ctx) + PK11_DestroyContext(ctx, PR_TRUE); + return rv; } /* @@ -275,103 +319,119 @@ loser: SECStatus PK11SDR_Decrypt(SECItem *data, SECItem *result, void *cx) { - SECStatus rv = SECSuccess; - PK11SlotInfo *slot = 0; - PK11SymKey *key = 0; - CK_MECHANISM_TYPE type; - SDRResult sdrResult; - SECItem *params = 0; - SECItem possibleResult = { 0, NULL, 0 }; - PLArenaPool *arena = 0; - - arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if (!arena) { rv = SECFailure; goto loser; } - - /* Decode the incoming data */ - memset(&sdrResult, 0, sizeof sdrResult); - rv = SEC_QuickDERDecodeItem(arena, &sdrResult, template, data); - if (rv != SECSuccess) goto loser; /* Invalid format */ - - /* Find the slot and key for the given keyid */ - slot = PK11_GetInternalKeySlot(); - if (!slot) { rv = SECFailure; goto loser; } - - rv = PK11_Authenticate(slot, PR_TRUE, cx); - if (rv != SECSuccess) goto loser; - - /* Get the parameter values from the data */ - params = PK11_ParamFromAlgid(&sdrResult.alg); - if (!params) { rv = SECFailure; goto loser; } - - /* Use triple-DES (Should look up the algorithm) */ - type = CKM_DES3_CBC; - key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx); - if (!key) { - rv = SECFailure; - } else { - rv = pk11Decrypt(slot, arena, type, key, params, - &sdrResult.data, result); - } - - /* - * if the pad value was too small (1 or 2), then it's statistically - * 'likely' that (1 in 256) that we may not have the correct key. - * Check the other keys for a better match. If we find none, use - * this result. - */ - if (rv == SECWouldBlock) { - possibleResult = *result; - } + SECStatus rv = SECSuccess; + PK11SlotInfo *slot = 0; + PK11SymKey *key = 0; + CK_MECHANISM_TYPE type; + SDRResult sdrResult; + SECItem *params = 0; + SECItem possibleResult = { 0, NULL, 0 }; + PLArenaPool *arena = 0; + + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (!arena) { + rv = SECFailure; + goto loser; + } - /* - * handle the case where your key indicies may have been broken - */ - if (rv != SECSuccess) { - PK11SymKey *keyList = PK11_ListFixedKeysInSlot(slot, NULL, cx); - PK11SymKey *testKey = NULL; - PK11SymKey *nextKey = NULL; - - for (testKey = keyList; testKey; - testKey = PK11_GetNextSymKey(testKey)) { - rv = pk11Decrypt(slot, arena, type, testKey, params, - &sdrResult.data, result); - if (rv == SECSuccess) { - break; - } - /* found a close match. If it's our first remember it */ - if (rv == SECWouldBlock) { - if (possibleResult.data) { - /* this is unlikely but possible. If we hit this condition, - * we have no way of knowing which possibility to prefer. - * in this case we just match the key the application - * thought was the right one */ - SECITEM_ZfreeItem(result, PR_FALSE); - } else { - possibleResult = *result; - } - } - } - - /* free the list */ - for (testKey = keyList; testKey; testKey = nextKey) { - nextKey = PK11_GetNextSymKey(testKey); - PK11_FreeSymKey(testKey); - } - } - - /* we didn't find a better key, use the one with a small pad value */ - if ((rv != SECSuccess) && (possibleResult.data)) { - *result = possibleResult; - possibleResult.data = NULL; - rv = SECSuccess; - } + /* Decode the incoming data */ + memset(&sdrResult, 0, sizeof sdrResult); + rv = SEC_QuickDERDecodeItem(arena, &sdrResult, template, data); + if (rv != SECSuccess) + goto loser; /* Invalid format */ + + /* Find the slot and key for the given keyid */ + slot = PK11_GetInternalKeySlot(); + if (!slot) { + rv = SECFailure; + goto loser; + } -loser: - if (arena) PORT_FreeArena(arena, PR_TRUE); - if (key) PK11_FreeSymKey(key); - if (params) SECITEM_ZfreeItem(params, PR_TRUE); - if (slot) PK11_FreeSlot(slot); - if (possibleResult.data) SECITEM_ZfreeItem(&possibleResult, PR_FALSE); + rv = PK11_Authenticate(slot, PR_TRUE, cx); + if (rv != SECSuccess) + goto loser; + + /* Get the parameter values from the data */ + params = PK11_ParamFromAlgid(&sdrResult.alg); + if (!params) { + rv = SECFailure; + goto loser; + } - return rv; + /* Use triple-DES (Should look up the algorithm) */ + type = CKM_DES3_CBC; + key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx); + if (!key) { + rv = SECFailure; + } else { + rv = pk11Decrypt(slot, arena, type, key, params, + &sdrResult.data, result); + } + + /* + * if the pad value was too small (1 or 2), then it's statistically + * 'likely' that (1 in 256) that we may not have the correct key. + * Check the other keys for a better match. If we find none, use + * this result. + */ + if (rv == SECWouldBlock) { + possibleResult = *result; + } + + /* + * handle the case where your key indicies may have been broken + */ + if (rv != SECSuccess) { + PK11SymKey *keyList = PK11_ListFixedKeysInSlot(slot, NULL, cx); + PK11SymKey *testKey = NULL; + PK11SymKey *nextKey = NULL; + + for (testKey = keyList; testKey; + testKey = PK11_GetNextSymKey(testKey)) { + rv = pk11Decrypt(slot, arena, type, testKey, params, + &sdrResult.data, result); + if (rv == SECSuccess) { + break; + } + /* found a close match. If it's our first remember it */ + if (rv == SECWouldBlock) { + if (possibleResult.data) { + /* this is unlikely but possible. If we hit this condition, + * we have no way of knowing which possibility to prefer. + * in this case we just match the key the application + * thought was the right one */ + SECITEM_ZfreeItem(result, PR_FALSE); + } else { + possibleResult = *result; + } + } + } + + /* free the list */ + for (testKey = keyList; testKey; testKey = nextKey) { + nextKey = PK11_GetNextSymKey(testKey); + PK11_FreeSymKey(testKey); + } + } + + /* we didn't find a better key, use the one with a small pad value */ + if ((rv != SECSuccess) && (possibleResult.data)) { + *result = possibleResult; + possibleResult.data = NULL; + rv = SECSuccess; + } + +loser: + if (arena) + PORT_FreeArena(arena, PR_TRUE); + if (key) + PK11_FreeSymKey(key); + if (params) + SECITEM_ZfreeItem(params, PR_TRUE); + if (slot) + PK11_FreeSlot(slot); + if (possibleResult.data) + SECITEM_ZfreeItem(&possibleResult, PR_FALSE); + + return rv; } |