diff --git a/cmd/bltest/blapitest.c b/cmd/bltest/blapitest.c index 06654ef655..76b9494f0e 100644 --- a/cmd/bltest/blapitest.c +++ b/cmd/bltest/blapitest.c @@ -21,6 +21,7 @@ #include "secoid.h" #include "nssutil.h" #include "ecl-curve.h" +#include "chacha20poly1305.h" #include "pkcs1_vectors.h" @@ -628,19 +629,20 @@ typedef enum { bltestSEED_ECB, /* SEED algorithm */ bltestSEED_CBC, /* SEED algorithm */ #endif - bltestCHACHA20, /* ChaCha20 + Poly1305 */ - bltestRSA, /* Public Key Ciphers */ - bltestRSA_OAEP, /* . (Public Key Enc.) */ - bltestRSA_PSS, /* . (Public Key Sig.) */ - bltestECDSA, /* . (Public Key Sig.) */ - bltestDSA, /* . (Public Key Sig.) */ - bltestMD2, /* Hash algorithms */ - bltestMD5, /* . */ - bltestSHA1, /* . */ - bltestSHA224, /* . */ - bltestSHA256, /* . */ - bltestSHA384, /* . */ - bltestSHA512, /* . */ + bltestCHACHA20_CTR, /* ChaCha20 block cipher */ + bltestCHACHA20, /* ChaCha20 + Poly1305 */ + bltestRSA, /* Public Key Ciphers */ + bltestRSA_OAEP, /* . (Public Key Enc.) */ + bltestRSA_PSS, /* . (Public Key Sig.) */ + bltestECDSA, /* . (Public Key Sig.) */ + bltestDSA, /* . (Public Key Sig.) */ + bltestMD2, /* Hash algorithms */ + bltestMD5, /* . */ + bltestSHA1, /* . */ + bltestSHA224, /* . */ + bltestSHA256, /* . */ + bltestSHA384, /* . */ + bltestSHA512, /* . */ NUMMODES } bltestCipherMode; @@ -670,6 +672,7 @@ static char *mode_strings[] = "seed_ecb", "seed_cbc", #endif + "chacha20_ctr", "chacha20_poly1305", "rsa", "rsa_oaep", @@ -801,11 +804,7 @@ PRBool is_symmkeyCipher(bltestCipherMode mode) { /* change as needed! */ -#ifndef NSS_DISABLE_DEPRECATED_SEED - if (mode >= bltestDES_ECB && mode <= bltestSEED_CBC) -#else - if (mode >= bltestDES_ECB && mode <= bltestCAMELLIA_CBC) -#endif + if (mode >= bltestDES_ECB && mode <= bltestCHACHA20_CTR) return PR_TRUE; return PR_FALSE; } @@ -842,6 +841,7 @@ is_singleShotCipher(bltestCipherMode mode) switch (mode) { case bltestAES_GCM: case bltestAES_CTS: + case bltestCHACHA20_CTR: case bltestCHACHA20: return PR_TRUE; default: @@ -897,6 +897,7 @@ cipher_requires_IV(bltestCipherMode mode) #ifndef NSS_DISABLE_DEPRECATED_SEED case bltestSEED_CBC: #endif + case bltestCHACHA20_CTR: case bltestCHACHA20: return PR_TRUE; default: @@ -1150,6 +1151,22 @@ aes_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen, input, inputLen); } +SECStatus +chacha20_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, const unsigned char *input, + unsigned int inputLen) +{ + if (maxOutputLen < inputLen) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } + ChaCha20Context *ctx = cx; + *outputLen = inputLen; + return ChaCha20_Xor(output, input, inputLen, ctx->key, ctx->nonce, + ctx->counter); + +} + SECStatus chacha20_poly1305_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, @@ -1655,6 +1672,24 @@ bltest_seed_init(bltestCipherInfo *cipherInfo, PRBool encrypt) } #endif /* NSS_DISABLE_DEPRECATED_SEED */ +SECStatus +bltest_chacha20_ctr_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + const PRUint32 counter = 1; + bltestSymmKeyParams *sk = &cipherInfo->params.sk; + cipherInfo->cx = ChaCha20_CreateContext(sk->key.buf.data, sk->key.buf.len, + sk->iv.buf.data, sk->iv.buf.len, + counter); + + if (cipherInfo->cx == NULL){ + PR_fprintf(PR_STDERR, "ChaCha20_CreateContext() returned NULL\n" + "key must be 32 bytes, iv must be 12 bytes\n"); + return SECFailure; + } + cipherInfo->cipher.symmkeyCipher = chacha20_Encrypt; + return SECSuccess; +} + SECStatus bltest_chacha20_init(bltestCipherInfo *cipherInfo, PRBool encrypt) { @@ -2316,6 +2351,11 @@ cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt) return bltest_seed_init(cipherInfo, encrypt); break; #endif /* NSS_DISABLE_DEPRECATED_SEED */ + case bltestCHACHA20_CTR: + outlen = cipherInfo->input.pBuf.len; + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, outlen); + return bltest_chacha20_ctr_init(cipherInfo, encrypt); + break; case bltestCHACHA20: outlen = cipherInfo->input.pBuf.len + (encrypt ? 16 : 0); SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, outlen); @@ -2620,6 +2660,9 @@ cipherFinish(bltestCipherInfo *cipherInfo) SEED_DestroyContext((SEEDContext *)cipherInfo->cx, PR_TRUE); break; #endif /* NSS_DISABLE_DEPRECATED_SEED */ + case bltestCHACHA20_CTR: + ChaCha20_DestroyContext((ChaCha20Context *)cipherInfo->cx, PR_TRUE); + break; case bltestCHACHA20: ChaCha20Poly1305_DestroyContext((ChaCha20Poly1305Context *) cipherInfo->cx, @@ -2706,7 +2749,10 @@ getHighUnitBytes(PRInt64 res) } } - return PR_smprintf("%d%s", spl[i], marks[i]); + if (i==0) + return PR_smprintf("%d%s", spl[i], marks[i]); + else + return PR_smprintf("%d%s %d%s", spl[i], marks[i], spl[i-1], marks[i-1]); } static void diff --git a/lib/freebl/blapi.h b/lib/freebl/blapi.h index 6f806884ea..3d1ff72691 100644 --- a/lib/freebl/blapi.h +++ b/lib/freebl/blapi.h @@ -1041,6 +1041,27 @@ Camellia_Decrypt(CamelliaContext *cx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen); +/******************************************/ +/* +** ChaCha20 block cipher +*/ + +extern SECStatus ChaCha20_InitContext(ChaCha20Context *ctx, + const unsigned char *key, + unsigned int keyLen, + const unsigned char *nonce, + unsigned int nonceLen, + PRUint32 ctr); + +extern ChaCha20Context *ChaCha20_CreateContext(const unsigned char *key, + unsigned int keyLen, + const unsigned char *nonce, + unsigned int nonceLen, + PRUint32 ctr); + +extern void ChaCha20_DestroyContext(ChaCha20Context *ctx, PRBool freeit); + + /******************************************/ /* ** ChaCha20+Poly1305 AEAD diff --git a/lib/freebl/blapit.h b/lib/freebl/blapit.h index 03cf963810..0054e17b85 100644 --- a/lib/freebl/blapit.h +++ b/lib/freebl/blapit.h @@ -245,6 +245,7 @@ struct SHA256ContextStr; struct SHA512ContextStr; struct AESKeyWrapContextStr; struct SEEDContextStr; +struct ChaCha20ContextStr; struct ChaCha20Poly1305ContextStr; struct Blake2bContextStr; @@ -265,6 +266,7 @@ typedef struct SHA512ContextStr SHA512Context; typedef struct SHA512ContextStr SHA384Context; typedef struct AESKeyWrapContextStr AESKeyWrapContext; typedef struct SEEDContextStr SEEDContext; +typedef struct ChaCha20ContextStr ChaCha20Context; typedef struct ChaCha20Poly1305ContextStr ChaCha20Poly1305Context; typedef struct Blake2bContextStr BLAKE2BContext; diff --git a/lib/freebl/chacha20poly1305.c b/lib/freebl/chacha20poly1305.c index aa1a63fe41..746fdb7a20 100644 --- a/lib/freebl/chacha20poly1305.c +++ b/lib/freebl/chacha20poly1305.c @@ -83,6 +83,66 @@ Chacha20Poly1305_vsx_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen, uint8_t *aad, uint32_t mlen, uint8_t *m, uint8_t *cipher, uint8_t *mac); +SECStatus +ChaCha20_InitContext(ChaCha20Context *ctx, const unsigned char *key, + unsigned int keyLen, const unsigned char *nonce, + unsigned int nonceLen, PRUint32 ctr) +{ +#ifdef NSS_DISABLE_CHACHAPOLY + return SECFailure; +#else + if (keyLen != 32) { + PORT_SetError(SEC_ERROR_BAD_KEY); + return SECFailure; + } + if (nonceLen != 12) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + ctx->counter = ctr; + PORT_Memcpy(ctx->key, key, sizeof(ctx->key)); + PORT_Memcpy(ctx->nonce, nonce, sizeof(ctx->nonce)); + + return SECSuccess; +#endif +} + +ChaCha20Context * +ChaCha20_CreateContext(const unsigned char *key, unsigned int keyLen, + const unsigned char *nonce, unsigned int nonceLen, + PRUint32 ctr) +{ +#ifdef NSS_DISABLE_CHACHAPOLY + return NULL; +#else + ChaCha20Context *ctx; + + ctx = PORT_New(ChaCha20Context); + if (ctx == NULL) { + return NULL; + } + + if (ChaCha20_InitContext(ctx, key, keyLen, nonce, nonceLen, ctr) != SECSuccess) { + PORT_Free(ctx); + ctx = NULL; + } + + return ctx; +#endif +} + +void +ChaCha20_DestroyContext(ChaCha20Context *ctx, PRBool freeit) +{ +#ifndef NSS_DISABLE_CHACHAPOLY + PORT_Memset(ctx, 0, sizeof(*ctx)); + if (freeit) { + PORT_Free(ctx); + } +#endif +} + SECStatus ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx, const unsigned char *key, unsigned int keyLen, diff --git a/lib/freebl/chacha20poly1305.h b/lib/freebl/chacha20poly1305.h index c77632aa13..fff528af39 100644 --- a/lib/freebl/chacha20poly1305.h +++ b/lib/freebl/chacha20poly1305.h @@ -12,4 +12,10 @@ struct ChaCha20Poly1305ContextStr { unsigned char tagLen; }; +struct ChaCha20ContextStr { + unsigned char key[32]; + unsigned char nonce[12]; + PRUint32 counter; +}; + #endif /* _CHACHA20_POLY1305_H_ */ diff --git a/lib/freebl/ldvector.c b/lib/freebl/ldvector.c index f14425f21d..ac3b862b56 100644 --- a/lib/freebl/ldvector.c +++ b/lib/freebl/ldvector.c @@ -371,9 +371,14 @@ static const struct FREEBLVectorStr vector = AESKeyWrap_DecryptKWP, /* End of version 3.023 */ - KEA_PrimeCheck + KEA_PrimeCheck, /* End of version 3.024 */ + ChaCha20_InitContext, + ChaCha20_CreateContext, + ChaCha20_DestroyContext + + /* End of version 3.025 */ }; const FREEBLVector* diff --git a/lib/freebl/loader.c b/lib/freebl/loader.c index 891516fa5f..3c61471de2 100644 --- a/lib/freebl/loader.c +++ b/lib/freebl/loader.c @@ -2158,6 +2158,36 @@ ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len return (vector->p_ChaCha20_Xor)(output, block, len, k, nonce, ctr); } +SECStatus +ChaCha20_InitContext(ChaCha20Context *ctx, const unsigned char *key, + unsigned int keyLen, + const unsigned char *nonce, + unsigned int nonceLen, + PRUint32 ctr) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_ChaCha20_InitContext)(ctx, key, keyLen, nonce, nonceLen, ctr); +} + +ChaCha20Context * +ChaCha20_CreateContext(const unsigned char *key, unsigned int keyLen, + const unsigned char *nonce, unsigned int nonceLen, + PRUint32 ctr) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_ChaCha20_CreateContext)(key, keyLen, nonce, nonceLen, ctr); +} + +void +ChaCha20_DestroyContext(ChaCha20Context *ctx, PRBool freeit) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_ChaCha20_DestroyContext)(ctx, freeit); +} + SECStatus ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx, const unsigned char *key, unsigned int keyLen, diff --git a/lib/freebl/loader.h b/lib/freebl/loader.h index 0b5ee5ef0d..eb3046d272 100644 --- a/lib/freebl/loader.h +++ b/lib/freebl/loader.h @@ -10,7 +10,7 @@ #include "blapi.h" -#define FREEBL_VERSION 0x0324 +#define FREEBL_VERSION 0x0325 struct FREEBLVectorStr { @@ -815,6 +815,23 @@ struct FREEBLVectorStr { PRBool (*p_KEA_PrimeCheck)(SECItem *prime); /* Version 3.024 came to here */ + SECStatus (*p_ChaCha20_InitContext)(ChaCha20Context *ctx, + const unsigned char *key, + unsigned int keyLen, + const unsigned char *nonce, + unsigned int nonceLen, + PRUint32 ctr); + + ChaCha20Context *(*p_ChaCha20_CreateContext)(const unsigned char *key, + unsigned int keyLen, + const unsigned char *nonce, + unsigned int nonceLen, + PRUint32 ctr); + + void (*p_ChaCha20_DestroyContext)(ChaCha20Context *ctx, PRBool freeit); + + /* Version 3.025 came to here */ + /* Add new function pointers at the end of this struct and bump * FREEBL_VERSION at the beginning of this file. */ };