| Index: nss/lib/softoken/pkcs11c.c
|
| ===================================================================
|
| --- nss/lib/softoken/pkcs11c.c (revision 228205)
|
| +++ nss/lib/softoken/pkcs11c.c (working copy)
|
| @@ -475,6 +475,110 @@
|
| maxLen, input, inputLen);
|
| }
|
|
|
| +/* sftk_ChaCha20Poly1305_Context saves the key and additional data for a
|
| + * ChaCha20+Poly1305 AEAD operation. */
|
| +struct sftk_ChaCha20Poly1305_Context {
|
| + unsigned char key[32];
|
| + unsigned char nonce[8];
|
| + unsigned char ad[16];
|
| + unsigned char *adOverflow;
|
| + unsigned int adLen;
|
| + unsigned char tagLen;
|
| +};
|
| +
|
| +static struct sftk_ChaCha20Poly1305_Context* sftk_ChaCha20Poly1305_New(
|
| + const unsigned char *key,
|
| + const CK_AEAD_PARAMS* params) {
|
| + struct sftk_ChaCha20Poly1305_Context* ctx;
|
| +
|
| + if (params->ulIvLen != sizeof(ctx->nonce))
|
| + return NULL;
|
| +
|
| + if (params->ulTagBits == 0 ||
|
| + params->ulTagBits > 128 ||
|
| + (params->ulTagBits & 3) != 0) {
|
| + return NULL;
|
| + }
|
| +
|
| + ctx = PORT_Alloc(sizeof(struct sftk_ChaCha20Poly1305_Context));
|
| + if (ctx == NULL)
|
| + return NULL;
|
| +
|
| + memcpy(ctx->nonce, params->pIv, sizeof(ctx->nonce));
|
| + memcpy(ctx->key, key, sizeof(ctx->key));
|
| + ctx->tagLen = params->ulTagBits >> 3;
|
| +
|
| + if (params->ulAADLen > sizeof(ctx->ad)) {
|
| + /* Need to allocate an overflow buffer for the additional data. */
|
| + ctx->adOverflow = PORT_Alloc(params->ulAADLen);
|
| + if (!ctx->adOverflow) {
|
| + PORT_Free(ctx);
|
| + return NULL;
|
| + }
|
| + memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen);
|
| + } else {
|
| + ctx->adOverflow = NULL;
|
| + memcpy(ctx->ad, params->pAAD, params->ulAADLen);
|
| + }
|
| + ctx->adLen = params->ulAADLen;
|
| +
|
| + return ctx;
|
| +}
|
| +
|
| +static void sftk_ChaCha20Poly1305_Free(
|
| + struct sftk_ChaCha20Poly1305_Context *ctx) {
|
| + if (ctx->adOverflow != NULL) {
|
| + PORT_Free(ctx->adOverflow);
|
| + }
|
| + PORT_Free(ctx);
|
| +}
|
| +
|
| +static SECStatus sftk_ChaCha20Poly1305_Seal(
|
| + const struct sftk_ChaCha20Poly1305_Context *ctx,
|
| + unsigned char *output,
|
| + unsigned int *outputLen,
|
| + unsigned int maxOutputLen,
|
| + const unsigned char *input,
|
| + unsigned int inputLen) {
|
| + const unsigned char* ad = ctx->adOverflow;
|
| +
|
| + if (maxOutputLen < inputLen + 16) {
|
| + return SECFailure;
|
| + }
|
| +
|
| + if (ad == NULL) {
|
| + ad = ctx->ad;
|
| + }
|
| +
|
| + *outputLen = inputLen + 16;
|
| +
|
| + return ChaCha20Poly1305_Seal(output, ad, ctx->adLen, input, inputLen,
|
| + ctx->tagLen, ctx->key, ctx->nonce);
|
| +}
|
| +
|
| +static SECStatus sftk_ChaCha20Poly1305_Open(
|
| + const struct sftk_ChaCha20Poly1305_Context *ctx,
|
| + unsigned char *output,
|
| + unsigned int *outputLen,
|
| + unsigned int maxOutputLen,
|
| + const unsigned char *input,
|
| + unsigned int inputLen) {
|
| + const unsigned char* ad = ctx->adOverflow;
|
| +
|
| + if (maxOutputLen < inputLen || inputLen < 16) {
|
| + return SECFailure;
|
| + }
|
| +
|
| + if (ad == NULL) {
|
| + ad = ctx->ad;
|
| + }
|
| +
|
| + *outputLen = inputLen - 16;
|
| +
|
| + return ChaCha20Poly1305_Open(output, ad, ctx->adLen, input, inputLen,
|
| + ctx->tagLen, ctx->key, ctx->nonce);
|
| +}
|
| +
|
| /** NSC_CryptInit initializes an encryption/Decryption operation.
|
| *
|
| * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
|
| @@ -870,6 +974,30 @@
|
| context->destroy = (SFTKDestroy) AES_DestroyContext;
|
| break;
|
|
|
| + case CKM_NSS_CHACHA20_POLY1305:
|
| + context->multi = PR_FALSE;
|
| + if (key_type != CKK_NSS_CHACHA20) {
|
| + crv = CKR_KEY_TYPE_INCONSISTENT;
|
| + break;
|
| + }
|
| + att = sftk_FindAttribute(key,CKA_VALUE);
|
| + if (att == NULL) {
|
| + crv = CKR_KEY_HANDLE_INVALID;
|
| + break;
|
| + }
|
| + context->cipherInfo = sftk_ChaCha20Poly1305_New(
|
| + (unsigned char*) att->attrib.pValue,
|
| + (CK_AEAD_PARAMS*) pMechanism->pParameter);
|
| + sftk_FreeAttribute(att);
|
| + if (context->cipherInfo == NULL) {
|
| + crv = CKR_HOST_MEMORY;
|
| + break;
|
| + }
|
| + context->update = (SFTKCipher) (isEncrypt ? sftk_ChaCha20Poly1305_Seal :
|
| + sftk_ChaCha20Poly1305_Open);
|
| + context->destroy = (SFTKDestroy) sftk_ChaCha20Poly1305_Free;
|
| + break;
|
| +
|
| case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
|
| context->doPad = PR_TRUE;
|
| /* fall thru */
|
| @@ -3272,6 +3400,10 @@
|
| *key_type = CKK_AES;
|
| if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
|
| break;
|
| + case CKM_NSS_CHACHA20_KEY_GEN:
|
| + *key_type = CKK_NSS_CHACHA20;
|
| + if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
|
| + break;
|
| default:
|
| PORT_Assert(0);
|
| crv = CKR_MECHANISM_INVALID;
|
| @@ -3516,6 +3648,7 @@
|
| case CKM_SEED_KEY_GEN:
|
| case CKM_CAMELLIA_KEY_GEN:
|
| case CKM_AES_KEY_GEN:
|
| + case CKM_NSS_CHACHA20_KEY_GEN:
|
| #if NSS_SOFTOKEN_DOES_RC5
|
| case CKM_RC5_KEY_GEN:
|
| #endif
|
|
|