Index: nss/lib/softoken/pkcs11c.c |
=================================================================== |
--- nss/lib/softoken/pkcs11c.c (revision 228205) |
+++ nss/lib/softoken/pkcs11c.c (working copy) |
@@ -475,6 +475,97 @@ |
maxLen, input, inputLen); |
} |
+static SFTKChaCha20Poly1305Info * |
+sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key, |
+ unsigned int keyLen, |
+ const CK_NSS_AEAD_PARAMS* params) |
+{ |
+ SFTKChaCha20Poly1305Info *ctx; |
+ |
+ if (params->ulIvLen != sizeof(ctx->nonce)) { |
+ PORT_SetError(SEC_ERROR_INPUT_LEN); |
+ return NULL; |
+ } |
+ |
+ ctx = PORT_New(SFTKChaCha20Poly1305Info); |
+ if (ctx == NULL) { |
+ return NULL; |
+ } |
+ |
+ if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen, |
+ params->ulTagLen) != SECSuccess) { |
+ PORT_Free(ctx); |
+ return NULL; |
+ } |
+ |
+ memcpy(ctx->nonce, params->pIv, sizeof(ctx->nonce)); |
+ |
+ if (params->ulAADLen > sizeof(ctx->ad)) { |
+ /* Need to allocate an overflow buffer for the additional data. */ |
+ ctx->adOverflow = (unsigned char *)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_DestroyContext(SFTKChaCha20Poly1305Info *ctx, |
+ PRBool freeit) |
+{ |
+ ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE); |
+ if (ctx->adOverflow != NULL) { |
+ PORT_Free(ctx->adOverflow); |
+ ctx->adOverflow = NULL; |
+ } |
+ ctx->adLen = 0; |
+ if (freeit) { |
+ PORT_Free(ctx); |
+ } |
+} |
+ |
+static SECStatus |
+sftk_ChaCha20Poly1305_Encrypt(const SFTKChaCha20Poly1305Info *ctx, |
+ unsigned char *output, unsigned int *outputLen, |
+ unsigned int maxOutputLen, |
+ const unsigned char *input, unsigned int inputLen) |
+{ |
+ const unsigned char *ad = ctx->adOverflow; |
+ |
+ if (ad == NULL) { |
+ ad = ctx->ad; |
+ } |
+ |
+ return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen, |
+ maxOutputLen, input, inputLen, ctx->nonce, |
+ sizeof(ctx->nonce), ad, ctx->adLen); |
+} |
+ |
+static SECStatus |
+sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx, |
+ unsigned char *output, unsigned int *outputLen, |
+ unsigned int maxOutputLen, |
+ const unsigned char *input, unsigned int inputLen) |
+{ |
+ const unsigned char *ad = ctx->adOverflow; |
+ |
+ if (ad == NULL) { |
+ ad = ctx->ad; |
+ } |
+ |
+ return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen, |
+ maxOutputLen, input, inputLen, ctx->nonce, |
+ sizeof(ctx->nonce), ad, ctx->adLen); |
+} |
+ |
/** NSC_CryptInit initializes an encryption/Decryption operation. |
* |
* Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. |
@@ -870,6 +961,35 @@ |
context->destroy = (SFTKDestroy) AES_DestroyContext; |
break; |
+ case CKM_NSS_CHACHA20_POLY1305: |
+ if (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS)) { |
+ crv = CKR_MECHANISM_PARAM_INVALID; |
+ break; |
+ } |
+ 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_CreateContext( |
+ (unsigned char*) att->attrib.pValue, att->attrib.ulValueLen, |
+ (CK_NSS_AEAD_PARAMS*) pMechanism->pParameter); |
+ sftk_FreeAttribute(att); |
+ if (context->cipherInfo == NULL) { |
+ crv = sftk_MapCryptError(PORT_GetError()); |
+ break; |
+ } |
+ context->update = (SFTKCipher) (isEncrypt ? |
+ sftk_ChaCha20Poly1305_Encrypt : |
+ sftk_ChaCha20Poly1305_Decrypt); |
+ context->destroy = (SFTKDestroy) sftk_ChaCha20Poly1305_DestroyContext; |
+ break; |
+ |
case CKM_NETSCAPE_AES_KEY_WRAP_PAD: |
context->doPad = PR_TRUE; |
/* fall thru */ |
@@ -3272,6 +3392,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 +3640,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 |