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 |