2018-05-04 16:08:28 +02:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifdef FREEBL_NO_DEPEND
|
|
|
|
#include "stubs.h"
|
|
|
|
#endif
|
|
|
|
#include "prtypes.h"
|
|
|
|
#include "blapit.h"
|
|
|
|
#include "blapii.h"
|
|
|
|
#include "ctr.h"
|
|
|
|
#include "pkcs11t.h"
|
|
|
|
#include "secerr.h"
|
|
|
|
|
cherry-picked mozilla NSS upstream changes (to rev f7a4c771997e, which is on par with 3.16.1 but without windows rand() changes):
9934c8faef29, 3c3b381c4865, 5a67f6beee9a, 1b1eb6d77728, a8b668fd72f7, bug962760, bug743700, bug857304, bug972653, bug972450, bug971358, bug903885, bug977073, bug976111, bug949939, bug947653, bug947572, bug903885, bug979106, bug966596, bug979004, bug979752, bug980848, bug938369, bug981170, bug668130, bug974693, bug975056, bug979132, bug370717, bug979070, bug985070, bug900067, bug977673, bug519255, bug989558, bug557299, bug987263, bug369802, a751a5146718, bug992343, bug952572, bug979703, bug994883, bug994869, bug993489, bug984608, bug977869, bug667371, bug672828, bug793347, bug977869
2018-07-10 17:07:31 +02:00
|
|
|
#ifdef USE_HW_AES
|
|
|
|
#include "intel-aes.h"
|
|
|
|
#include "rijndael.h"
|
|
|
|
#endif
|
|
|
|
|
2018-05-04 16:08:28 +02:00
|
|
|
SECStatus
|
|
|
|
CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher,
|
|
|
|
const unsigned char *param, unsigned int blocksize)
|
|
|
|
{
|
|
|
|
const CK_AES_CTR_PARAMS *ctrParams = (const CK_AES_CTR_PARAMS *)param;
|
|
|
|
|
|
|
|
if (ctrParams->ulCounterBits == 0 ||
|
|
|
|
ctrParams->ulCounterBits > blocksize * PR_BITS_PER_BYTE) {
|
|
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invariant: 0 < ctr->bufPtr <= blocksize */
|
|
|
|
ctr->bufPtr = blocksize; /* no unused data in the buffer */
|
|
|
|
ctr->cipher = cipher;
|
|
|
|
ctr->context = context;
|
|
|
|
ctr->counterBits = ctrParams->ulCounterBits;
|
|
|
|
if (blocksize > sizeof(ctr->counter) ||
|
|
|
|
blocksize > sizeof(ctrParams->cb)) {
|
|
|
|
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
PORT_Memcpy(ctr->counter, ctrParams->cb, blocksize);
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
CTRContext *
|
|
|
|
CTR_CreateContext(void *context, freeblCipherFunc cipher,
|
|
|
|
const unsigned char *param, unsigned int blocksize)
|
|
|
|
{
|
|
|
|
CTRContext *ctr;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
/* first fill in the Counter context */
|
|
|
|
ctr = PORT_ZNew(CTRContext);
|
|
|
|
if (ctr == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
rv = CTR_InitContext(ctr, context, cipher, param, blocksize);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
CTR_DestroyContext(ctr, PR_TRUE);
|
|
|
|
ctr = NULL;
|
|
|
|
}
|
|
|
|
return ctr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CTR_DestroyContext(CTRContext *ctr, PRBool freeit)
|
|
|
|
{
|
|
|
|
PORT_Memset(ctr, 0, sizeof(CTRContext));
|
|
|
|
if (freeit) {
|
|
|
|
PORT_Free(ctr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Used by counter mode. Increment the counter block. Not all bits in the
|
|
|
|
* counter block are part of the counter, counterBits tells how many bits
|
|
|
|
* are part of the counter. The counter block is blocksize long. It's a
|
|
|
|
* big endian value.
|
|
|
|
*
|
|
|
|
* XXX Does not handle counter rollover.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ctr_GetNextCtr(unsigned char *counter, unsigned int counterBits,
|
cherry-picked mozilla NSS upstream changes (to rev f7a4c771997e, which is on par with 3.16.1 but without windows rand() changes):
9934c8faef29, 3c3b381c4865, 5a67f6beee9a, 1b1eb6d77728, a8b668fd72f7, bug962760, bug743700, bug857304, bug972653, bug972450, bug971358, bug903885, bug977073, bug976111, bug949939, bug947653, bug947572, bug903885, bug979106, bug966596, bug979004, bug979752, bug980848, bug938369, bug981170, bug668130, bug974693, bug975056, bug979132, bug370717, bug979070, bug985070, bug900067, bug977673, bug519255, bug989558, bug557299, bug987263, bug369802, a751a5146718, bug992343, bug952572, bug979703, bug994883, bug994869, bug993489, bug984608, bug977869, bug667371, bug672828, bug793347, bug977869
2018-07-10 17:07:31 +02:00
|
|
|
unsigned int blocksize)
|
2018-05-04 16:08:28 +02:00
|
|
|
{
|
|
|
|
unsigned char *counterPtr = counter + blocksize - 1;
|
|
|
|
unsigned char mask, count;
|
|
|
|
|
|
|
|
PORT_Assert(counterBits <= blocksize*PR_BITS_PER_BYTE);
|
|
|
|
while (counterBits >= PR_BITS_PER_BYTE) {
|
|
|
|
if (++(*(counterPtr--))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
counterBits -= PR_BITS_PER_BYTE;
|
|
|
|
}
|
|
|
|
if (counterBits == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* increment the final partial byte */
|
|
|
|
mask = (1 << counterBits)-1;
|
|
|
|
count = ++(*counterPtr) & mask;
|
|
|
|
*counterPtr = ((*counterPtr) & ~mask) | count;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ctr_xor(unsigned char *target, const unsigned char *x,
|
cherry-picked mozilla NSS upstream changes (to rev f7a4c771997e, which is on par with 3.16.1 but without windows rand() changes):
9934c8faef29, 3c3b381c4865, 5a67f6beee9a, 1b1eb6d77728, a8b668fd72f7, bug962760, bug743700, bug857304, bug972653, bug972450, bug971358, bug903885, bug977073, bug976111, bug949939, bug947653, bug947572, bug903885, bug979106, bug966596, bug979004, bug979752, bug980848, bug938369, bug981170, bug668130, bug974693, bug975056, bug979132, bug370717, bug979070, bug985070, bug900067, bug977673, bug519255, bug989558, bug557299, bug987263, bug369802, a751a5146718, bug992343, bug952572, bug979703, bug994883, bug994869, bug993489, bug984608, bug977869, bug667371, bug672828, bug793347, bug977869
2018-07-10 17:07:31 +02:00
|
|
|
const unsigned char *y, unsigned int count)
|
2018-05-04 16:08:28 +02:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i=0; i < count; i++) {
|
|
|
|
*target++ = *x++ ^ *y++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECStatus
|
|
|
|
CTR_Update(CTRContext *ctr, unsigned char *outbuf,
|
cherry-picked mozilla NSS upstream changes (to rev f7a4c771997e, which is on par with 3.16.1 but without windows rand() changes):
9934c8faef29, 3c3b381c4865, 5a67f6beee9a, 1b1eb6d77728, a8b668fd72f7, bug962760, bug743700, bug857304, bug972653, bug972450, bug971358, bug903885, bug977073, bug976111, bug949939, bug947653, bug947572, bug903885, bug979106, bug966596, bug979004, bug979752, bug980848, bug938369, bug981170, bug668130, bug974693, bug975056, bug979132, bug370717, bug979070, bug985070, bug900067, bug977673, bug519255, bug989558, bug557299, bug987263, bug369802, a751a5146718, bug992343, bug952572, bug979703, bug994883, bug994869, bug993489, bug984608, bug977869, bug667371, bug672828, bug793347, bug977869
2018-07-10 17:07:31 +02:00
|
|
|
unsigned int *outlen, unsigned int maxout,
|
|
|
|
const unsigned char *inbuf, unsigned int inlen,
|
|
|
|
unsigned int blocksize)
|
2018-05-04 16:08:28 +02:00
|
|
|
{
|
|
|
|
unsigned int tmp;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
if (maxout < inlen) {
|
|
|
|
*outlen = inlen;
|
|
|
|
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
*outlen = 0;
|
|
|
|
if (ctr->bufPtr != blocksize) {
|
|
|
|
unsigned int needed = PR_MIN(blocksize-ctr->bufPtr, inlen);
|
cherry-picked mozilla NSS upstream changes (to rev f7a4c771997e, which is on par with 3.16.1 but without windows rand() changes):
9934c8faef29, 3c3b381c4865, 5a67f6beee9a, 1b1eb6d77728, a8b668fd72f7, bug962760, bug743700, bug857304, bug972653, bug972450, bug971358, bug903885, bug977073, bug976111, bug949939, bug947653, bug947572, bug903885, bug979106, bug966596, bug979004, bug979752, bug980848, bug938369, bug981170, bug668130, bug974693, bug975056, bug979132, bug370717, bug979070, bug985070, bug900067, bug977673, bug519255, bug989558, bug557299, bug987263, bug369802, a751a5146718, bug992343, bug952572, bug979703, bug994883, bug994869, bug993489, bug984608, bug977869, bug667371, bug672828, bug793347, bug977869
2018-07-10 17:07:31 +02:00
|
|
|
ctr_xor(outbuf, inbuf, ctr->buffer + ctr->bufPtr, needed);
|
2018-05-04 16:08:28 +02:00
|
|
|
ctr->bufPtr += needed;
|
|
|
|
outbuf += needed;
|
|
|
|
inbuf += needed;
|
|
|
|
*outlen += needed;
|
|
|
|
inlen -= needed;
|
|
|
|
if (inlen == 0) {
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
PORT_Assert(ctr->bufPtr == blocksize);
|
|
|
|
}
|
cherry-picked mozilla NSS upstream changes (to rev f7a4c771997e, which is on par with 3.16.1 but without windows rand() changes):
9934c8faef29, 3c3b381c4865, 5a67f6beee9a, 1b1eb6d77728, a8b668fd72f7, bug962760, bug743700, bug857304, bug972653, bug972450, bug971358, bug903885, bug977073, bug976111, bug949939, bug947653, bug947572, bug903885, bug979106, bug966596, bug979004, bug979752, bug980848, bug938369, bug981170, bug668130, bug974693, bug975056, bug979132, bug370717, bug979070, bug985070, bug900067, bug977673, bug519255, bug989558, bug557299, bug987263, bug369802, a751a5146718, bug992343, bug952572, bug979703, bug994883, bug994869, bug993489, bug984608, bug977869, bug667371, bug672828, bug793347, bug977869
2018-07-10 17:07:31 +02:00
|
|
|
|
2018-05-04 16:08:28 +02:00
|
|
|
while (inlen >= blocksize) {
|
|
|
|
rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
|
|
|
|
ctr->counter, blocksize, blocksize);
|
|
|
|
ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
ctr_xor(outbuf, inbuf, ctr->buffer, blocksize);
|
|
|
|
outbuf += blocksize;
|
|
|
|
inbuf += blocksize;
|
|
|
|
*outlen += blocksize;
|
|
|
|
inlen -= blocksize;
|
|
|
|
}
|
|
|
|
if (inlen == 0) {
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
|
|
|
|
ctr->counter, blocksize, blocksize);
|
|
|
|
ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
ctr_xor(outbuf, inbuf, ctr->buffer, inlen);
|
|
|
|
ctr->bufPtr = inlen;
|
|
|
|
*outlen += inlen;
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
cherry-picked mozilla NSS upstream changes (to rev f7a4c771997e, which is on par with 3.16.1 but without windows rand() changes):
9934c8faef29, 3c3b381c4865, 5a67f6beee9a, 1b1eb6d77728, a8b668fd72f7, bug962760, bug743700, bug857304, bug972653, bug972450, bug971358, bug903885, bug977073, bug976111, bug949939, bug947653, bug947572, bug903885, bug979106, bug966596, bug979004, bug979752, bug980848, bug938369, bug981170, bug668130, bug974693, bug975056, bug979132, bug370717, bug979070, bug985070, bug900067, bug977673, bug519255, bug989558, bug557299, bug987263, bug369802, a751a5146718, bug992343, bug952572, bug979703, bug994883, bug994869, bug993489, bug984608, bug977869, bug667371, bug672828, bug793347, bug977869
2018-07-10 17:07:31 +02:00
|
|
|
|
|
|
|
#if defined(USE_HW_AES) && defined(_MSC_VER)
|
|
|
|
SECStatus
|
|
|
|
CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf,
|
|
|
|
unsigned int *outlen, unsigned int maxout,
|
|
|
|
const unsigned char *inbuf, unsigned int inlen,
|
|
|
|
unsigned int blocksize)
|
|
|
|
{
|
|
|
|
unsigned int fullblocks;
|
|
|
|
unsigned int tmp;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
if (maxout < inlen) {
|
|
|
|
*outlen = inlen;
|
|
|
|
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
*outlen = 0;
|
|
|
|
if (ctr->bufPtr != blocksize) {
|
|
|
|
unsigned int needed = PR_MIN(blocksize-ctr->bufPtr, inlen);
|
|
|
|
ctr_xor(outbuf, inbuf, ctr->buffer + ctr->bufPtr, needed);
|
|
|
|
ctr->bufPtr += needed;
|
|
|
|
outbuf += needed;
|
|
|
|
inbuf += needed;
|
|
|
|
*outlen += needed;
|
|
|
|
inlen -= needed;
|
|
|
|
if (inlen == 0) {
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
PORT_Assert(ctr->bufPtr == blocksize);
|
|
|
|
}
|
|
|
|
|
|
|
|
intel_aes_ctr_worker(((AESContext*)(ctr->context))->Nr)(
|
|
|
|
ctr, outbuf, outlen, maxout, inbuf, inlen, blocksize);
|
|
|
|
/* XXX intel_aes_ctr_worker should set *outlen. */
|
|
|
|
PORT_Assert(*outlen == 0);
|
|
|
|
fullblocks = (inlen/blocksize)*blocksize;
|
|
|
|
*outlen += fullblocks;
|
|
|
|
outbuf += fullblocks;
|
|
|
|
inbuf += fullblocks;
|
|
|
|
inlen -= fullblocks;
|
|
|
|
|
|
|
|
if (inlen == 0) {
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
|
|
|
|
ctr->counter, blocksize, blocksize);
|
|
|
|
ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
ctr_xor(outbuf, inbuf, ctr->buffer, inlen);
|
|
|
|
ctr->bufPtr = inlen;
|
|
|
|
*outlen += inlen;
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
#endif
|