static bool ike_alg_nss_gcm(const struct encrypt_desc *alg, u_int8_t *salt, size_t salt_size, u_int8_t *wire_iv, size_t wire_iv_size, u_int8_t *aad, size_t aad_size, u_int8_t *text_and_tag, size_t text_size, size_t tag_size, PK11SymKey *sym_key, bool enc) { /* See pk11gcmtest.c */ bool ok = TRUE; chunk_t salt_chunk = { .ptr = salt, .len = salt_size, }; chunk_t wire_iv_chunk = { .ptr = wire_iv, .len = wire_iv_size, }; chunk_t iv = concat_chunk_chunk("IV", salt_chunk, wire_iv_chunk); CK_GCM_PARAMS gcm_params; gcm_params.pIv = iv.ptr; gcm_params.ulIvLen = iv.len; gcm_params.pAAD = aad; gcm_params.ulAADLen = aad_size; gcm_params.ulTagBits = tag_size * 8; SECItem param; param.type = siBuffer; param.data = (void*)&gcm_params; param.len = sizeof gcm_params; /* Output buffer for transformed data. */ size_t text_and_tag_size = text_size + tag_size; u_int8_t *out_buf = PR_Malloc(text_and_tag_size); unsigned int out_len = 0; if (enc) { SECStatus rv = PK11_Encrypt(sym_key, alg->common.nss_mechanism, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_size); if (rv != SECSuccess) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Encrypt failure (err %d)", PR_GetError()); ok = FALSE; } else if (out_len != text_and_tag_size) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Encrypt output length of %u not the expected %zd", out_len, text_and_tag_size); ok = FALSE; } } else { SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_GCM, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_and_tag_size); if (rv != SECSuccess) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Decrypt failure (err %d)", PR_GetError()); ok = FALSE; } else if (out_len != text_size) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Decrypt output length of %u not the expected %zd", out_len, text_size); ok = FALSE; } } memcpy(text_and_tag, out_buf, out_len); PR_Free(out_buf); freeanychunk(iv); return ok; }
static SECStatus aes_decrypt_buf( const unsigned char *key, unsigned int keysize, const unsigned char *iv, unsigned int ivsize, unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, const unsigned char *input, unsigned int inputlen, const unsigned char *aad, unsigned int aadlen, const unsigned char *tag, unsigned int tagsize) { SECStatus rv = SECFailure; unsigned char concatenated[11*16]; /* 1 to 11 blocks */ SECItem key_item; PK11SlotInfo *slot = NULL; PK11SymKey *symKey = NULL; CK_GCM_PARAMS gcm_params; SECItem param; if (inputlen + tagsize > sizeof(concatenated)) { fprintf(stderr, "aes_decrypt_buf: local buffer too small\n"); goto loser; } memcpy(concatenated, input, inputlen); memcpy(concatenated + inputlen, tag, tagsize); /* Import key into NSS. */ key_item.type = siBuffer; key_item.data = (unsigned char *) key; /* const cast */ key_item.len = keysize; slot = PK11_GetInternalSlot(); symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL); PK11_FreeSlot(slot); slot = NULL; if (!symKey) { fprintf(stderr, "PK11_ImportSymKey failed\n"); goto loser; } gcm_params.pIv = (unsigned char *) iv; gcm_params.ulIvLen = ivsize; gcm_params.pAAD = (unsigned char *) aad; gcm_params.ulAADLen = aadlen; gcm_params.ulTagBits = tagsize * 8; param.type = siBuffer; param.data = (unsigned char *) &gcm_params; param.len = sizeof(gcm_params); if (PK11_Decrypt(symKey, CKM_AES_GCM, ¶m, output, outputlen, maxoutputlen, concatenated, inputlen + tagsize) != SECSuccess) { goto loser; } rv = SECSuccess; loser: if (symKey != NULL) { PK11_FreeSymKey(symKey); } return rv; }
SECStatus ssl_SelfEncryptUnprotectInt( PK11SymKey *encKey, PK11SymKey *macKey, const unsigned char *keyName, const PRUint8 *in, unsigned int inLen, PRUint8 *out, unsigned int *outLen, unsigned int maxOutLen) { sslReader reader = SSL_READER(in, inLen); sslReadBuffer encodedKeyNameBuffer = { 0 }; SECStatus rv = sslRead_Read(&reader, SELF_ENCRYPT_KEY_NAME_LEN, &encodedKeyNameBuffer); if (rv != SECSuccess) { return SECFailure; } sslReadBuffer ivBuffer = { 0 }; rv = sslRead_Read(&reader, AES_BLOCK_SIZE, &ivBuffer); if (rv != SECSuccess) { return SECFailure; } PRUint64 cipherTextLen = 0; rv = sslRead_ReadNumber(&reader, 2, &cipherTextLen); if (rv != SECSuccess) { return SECFailure; } sslReadBuffer cipherTextBuffer = { 0 }; rv = sslRead_Read(&reader, (unsigned int)cipherTextLen, &cipherTextBuffer); if (rv != SECSuccess) { return SECFailure; } unsigned int bytesToMac = reader.offset; sslReadBuffer encodedMacBuffer = { 0 }; rv = sslRead_Read(&reader, SHA256_LENGTH, &encodedMacBuffer); if (rv != SECSuccess) { return SECFailure; } /* Make sure we're at the end of the block. */ if (reader.offset != reader.buf.len) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } /* Now that everything is decoded, we can make progress. */ /* 1. Check that we have the right key. */ if (PORT_Memcmp(keyName, encodedKeyNameBuffer.buf, SELF_ENCRYPT_KEY_NAME_LEN)) { PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT); return SECFailure; } /* 2. Check the MAC */ unsigned char computedMac[SHA256_LENGTH]; unsigned int computedMacLen = 0; rv = ssl_MacBuffer(macKey, CKM_SHA256_HMAC, in, bytesToMac, computedMac, &computedMacLen, sizeof(computedMac)); if (rv != SECSuccess) { return SECFailure; } PORT_Assert(computedMacLen == SHA256_LENGTH); if (NSS_SecureMemcmp(computedMac, encodedMacBuffer.buf, computedMacLen) != 0) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } /* 3. OK, it verifies, now decrypt. */ SECItem ivItem = { siBuffer, (unsigned char *)ivBuffer.buf, AES_BLOCK_SIZE }; rv = PK11_Decrypt(encKey, CKM_AES_CBC_PAD, &ivItem, out, outLen, maxOutLen, cipherTextBuffer.buf, cipherTextLen); if (rv != SECSuccess) { return SECFailure; } return SECSuccess; }