forked from wolfSSL/wolfssl
Merge branch 'master' of github.com:cyassl/cyassl
This commit is contained in:
@@ -1057,7 +1057,7 @@ int RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
|
||||
|
||||
key->type = RSA_PUBLIC;
|
||||
|
||||
#ifdef OPENSSL_EXTRA
|
||||
#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
|
||||
{
|
||||
byte b = input[*inOutIdx];
|
||||
if (b != ASN_INTEGER) {
|
||||
@@ -1272,6 +1272,11 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
|
||||
cert->subjectCNLen = 0;
|
||||
cert->subjectCNStored = 0;
|
||||
cert->altNames = NULL;
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
cert->altEmailNames = NULL;
|
||||
cert->permittedNames = NULL;
|
||||
cert->excludedNames = NULL;
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
cert->issuer[0] = '\0';
|
||||
cert->subject[0] = '\0';
|
||||
cert->source = source; /* don't own */
|
||||
@@ -1341,6 +1346,9 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
|
||||
cert->extSubjKeyIdSrc = NULL;
|
||||
cert->extSubjKeyIdSz = 0;
|
||||
#endif /* OPENSSL_EXTRA */
|
||||
#if defined(OPENSSL_EXTRA) || !defined(IGNORE_NAME_CONSTRAINTS)
|
||||
cert->extNameConstraintSet = 0;
|
||||
#endif /* OPENSSL_EXTRA || !IGNORE_NAME_CONSTRAINTS */
|
||||
#ifdef HAVE_ECC
|
||||
cert->pkCurveOID = 0;
|
||||
#endif /* HAVE_ECC */
|
||||
@@ -1372,6 +1380,22 @@ void FreeAltNames(DNS_entry* altNames, void* heap)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
|
||||
void FreeNameSubtrees(Base_entry* names, void* heap)
|
||||
{
|
||||
(void)heap;
|
||||
|
||||
while (names) {
|
||||
Base_entry* tmp = names->next;
|
||||
|
||||
XFREE(names->name, heap, DYNAMIC_TYPE_ALTNAME);
|
||||
XFREE(names, heap, DYNAMIC_TYPE_ALTNAME);
|
||||
names = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
|
||||
void FreeDecodedCert(DecodedCert* cert)
|
||||
{
|
||||
@@ -1381,6 +1405,14 @@ void FreeDecodedCert(DecodedCert* cert)
|
||||
XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
|
||||
if (cert->altNames)
|
||||
FreeAltNames(cert->altNames, cert->heap);
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
if (cert->altEmailNames)
|
||||
FreeAltNames(cert->altEmailNames, cert->heap);
|
||||
if (cert->permittedNames)
|
||||
FreeNameSubtrees(cert->permittedNames, cert->heap);
|
||||
if (cert->excludedNames)
|
||||
FreeNameSubtrees(cert->excludedNames, cert->heap);
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
#ifdef CYASSL_SEP
|
||||
XFREE(cert->deviceType, cert->heap, 0);
|
||||
XFREE(cert->hwType, cert->heap, 0);
|
||||
@@ -1419,8 +1451,6 @@ static int GetCertHeader(DecodedCert* cert)
|
||||
len = mp_unsigned_bin_size(&mpi);
|
||||
if (len < (int)sizeof(serialTmp)) {
|
||||
if ( (ret = mp_to_unsigned_bin(&mpi, serialTmp)) == MP_OKAY) {
|
||||
if (len > EXTERNAL_SERIAL_SIZE)
|
||||
len = EXTERNAL_SERIAL_SIZE;
|
||||
XMEMCPY(cert->serial, serialTmp, len);
|
||||
cert->serialSz = len;
|
||||
}
|
||||
@@ -1640,6 +1670,12 @@ static int GetName(DecodedCert* cert, int nameType)
|
||||
cert->issuerRawLen = length - cert->srcIdx;
|
||||
}
|
||||
#endif
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
if (nameType == SUBJECT) {
|
||||
cert->subjectRaw = &cert->source[cert->srcIdx];
|
||||
cert->subjectRawLen = length - cert->srcIdx;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (cert->srcIdx < (word32)length) {
|
||||
byte b;
|
||||
@@ -1863,7 +1899,30 @@ static int GetName(DecodedCert* cert, int nameType)
|
||||
dName->emailIdx = cert->srcIdx;
|
||||
dName->emailLen = adv;
|
||||
#endif /* OPENSSL_EXTRA */
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
{
|
||||
DNS_entry* emailName = NULL;
|
||||
|
||||
emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
|
||||
cert->heap, DYNAMIC_TYPE_ALTNAME);
|
||||
if (emailName == NULL) {
|
||||
CYASSL_MSG("\tOut of Memory");
|
||||
return MEMORY_E;
|
||||
}
|
||||
emailName->name = (char*)XMALLOC(adv + 1,
|
||||
cert->heap, DYNAMIC_TYPE_ALTNAME);
|
||||
if (emailName->name == NULL) {
|
||||
CYASSL_MSG("\tOut of Memory");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMCPY(emailName->name,
|
||||
&cert->source[cert->srcIdx], adv);
|
||||
emailName->name[adv] = 0;
|
||||
|
||||
emailName->next = cert->altEmailNames;
|
||||
cert->altEmailNames = emailName;
|
||||
}
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
if (!tooBig) {
|
||||
XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
|
||||
idx += adv;
|
||||
@@ -2057,7 +2116,7 @@ static int DateGreaterThan(const struct tm* a, const struct tm* b)
|
||||
|
||||
static INLINE int DateLessThan(const struct tm* a, const struct tm* b)
|
||||
{
|
||||
return !DateGreaterThan(a,b);
|
||||
return DateGreaterThan(b,a);
|
||||
}
|
||||
|
||||
|
||||
@@ -2870,6 +2929,174 @@ static int ConfirmSignature(const byte* buf, word32 bufSz,
|
||||
}
|
||||
|
||||
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
|
||||
static int MatchBaseName(int type, const char* name, int nameSz,
|
||||
const char* base, int baseSz)
|
||||
{
|
||||
if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 ||
|
||||
name[0] == '.' || nameSz < baseSz ||
|
||||
(type != ASN_RFC822_TYPE && type != ASN_DNS_TYPE))
|
||||
return 0;
|
||||
|
||||
/* If an email type, handle special cases where the base is only
|
||||
* a domain, or is an email address itself. */
|
||||
if (type == ASN_RFC822_TYPE) {
|
||||
const char* p = NULL;
|
||||
int count = 0;
|
||||
|
||||
if (base[0] != '.') {
|
||||
p = base;
|
||||
count = 0;
|
||||
|
||||
/* find the '@' in the base */
|
||||
while (*p != '@' && count < baseSz) {
|
||||
count++;
|
||||
p++;
|
||||
}
|
||||
|
||||
/* No '@' in base, reset p to NULL */
|
||||
if (count >= baseSz)
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
if (p == NULL) {
|
||||
/* Base isn't an email address, it is a domain name,
|
||||
* wind the name forward one character past its '@'. */
|
||||
p = name;
|
||||
count = 0;
|
||||
while (*p != '@' && count < baseSz) {
|
||||
count++;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (count < baseSz && *p == '@') {
|
||||
name = p + 1;
|
||||
nameSz -= count + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((type == ASN_DNS_TYPE || type == ASN_RFC822_TYPE) && base[0] == '.') {
|
||||
int szAdjust = nameSz - baseSz;
|
||||
name += szAdjust;
|
||||
nameSz -= szAdjust;
|
||||
}
|
||||
|
||||
while (nameSz > 0) {
|
||||
if (XTOLOWER(*name++) != XTOLOWER(*base++))
|
||||
return 0;
|
||||
nameSz--;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
|
||||
{
|
||||
if (signer == NULL || cert == NULL)
|
||||
return 0;
|
||||
|
||||
/* Check against the excluded list */
|
||||
if (signer->excludedNames) {
|
||||
Base_entry* base = signer->excludedNames;
|
||||
|
||||
while (base != NULL) {
|
||||
if (base->type == ASN_DNS_TYPE) {
|
||||
DNS_entry* name = cert->altNames;
|
||||
while (name != NULL) {
|
||||
if (MatchBaseName(ASN_DNS_TYPE,
|
||||
name->name, (int)XSTRLEN(name->name),
|
||||
base->name, base->nameSz))
|
||||
return 0;
|
||||
name = name->next;
|
||||
}
|
||||
}
|
||||
else if (base->type == ASN_RFC822_TYPE) {
|
||||
DNS_entry* name = cert->altEmailNames;
|
||||
while (name != NULL) {
|
||||
if (MatchBaseName(ASN_RFC822_TYPE,
|
||||
name->name, (int)XSTRLEN(name->name),
|
||||
base->name, base->nameSz))
|
||||
return 0;
|
||||
|
||||
name = name->next;
|
||||
}
|
||||
}
|
||||
else if (base->type == ASN_DIR_TYPE) {
|
||||
if (cert->subjectRawLen == base->nameSz &&
|
||||
XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
base = base->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check against the permitted list */
|
||||
if (signer->permittedNames != NULL) {
|
||||
int needDns = 0;
|
||||
int matchDns = 0;
|
||||
int needEmail = 0;
|
||||
int matchEmail = 0;
|
||||
int needDir = 0;
|
||||
int matchDir = 0;
|
||||
Base_entry* base = signer->permittedNames;
|
||||
|
||||
while (base != NULL) {
|
||||
if (base->type == ASN_DNS_TYPE) {
|
||||
DNS_entry* name = cert->altNames;
|
||||
|
||||
if (name != NULL)
|
||||
needDns = 1;
|
||||
|
||||
while (name != NULL) {
|
||||
matchDns = MatchBaseName(ASN_DNS_TYPE,
|
||||
name->name, (int)XSTRLEN(name->name),
|
||||
base->name, base->nameSz);
|
||||
name = name->next;
|
||||
}
|
||||
}
|
||||
else if (base->type == ASN_RFC822_TYPE) {
|
||||
DNS_entry* name = cert->altEmailNames;
|
||||
|
||||
if (name != NULL)
|
||||
needEmail = 1;
|
||||
|
||||
while (name != NULL) {
|
||||
matchEmail = MatchBaseName(ASN_DNS_TYPE,
|
||||
name->name, (int)XSTRLEN(name->name),
|
||||
base->name, base->nameSz);
|
||||
name = name->next;
|
||||
}
|
||||
}
|
||||
else if (base->type == ASN_DIR_TYPE) {
|
||||
needDir = 1;
|
||||
if (cert->subjectRaw != NULL &&
|
||||
cert->subjectRawLen == base->nameSz &&
|
||||
XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
|
||||
|
||||
matchDir = 1;
|
||||
}
|
||||
}
|
||||
base = base->next;
|
||||
}
|
||||
|
||||
if ((needDns && !matchDns) || (needEmail && !matchEmail) ||
|
||||
(needDir && !matchDir)) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
|
||||
|
||||
static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
|
||||
{
|
||||
word32 idx = 0;
|
||||
@@ -2924,6 +3151,43 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
|
||||
length -= strLen;
|
||||
idx += strLen;
|
||||
}
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
|
||||
DNS_entry* emailEntry;
|
||||
int strLen;
|
||||
word32 lenStartIdx = idx;
|
||||
|
||||
if (GetLength(input, &idx, &strLen, sz) < 0) {
|
||||
CYASSL_MSG("\tfail: str length");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
length -= (idx - lenStartIdx);
|
||||
|
||||
emailEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
|
||||
DYNAMIC_TYPE_ALTNAME);
|
||||
if (emailEntry == NULL) {
|
||||
CYASSL_MSG("\tOut of Memory");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
|
||||
DYNAMIC_TYPE_ALTNAME);
|
||||
if (emailEntry->name == NULL) {
|
||||
CYASSL_MSG("\tOut of Memory");
|
||||
XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
XMEMCPY(emailEntry->name, &input[idx], strLen);
|
||||
emailEntry->name[strLen] = '\0';
|
||||
|
||||
emailEntry->next = cert->altEmailNames;
|
||||
cert->altEmailNames = emailEntry;
|
||||
|
||||
length -= strLen;
|
||||
idx += strLen;
|
||||
}
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
#ifdef CYASSL_SEP
|
||||
else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE))
|
||||
{
|
||||
@@ -3329,7 +3593,7 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
|
||||
CYASSL_ENTER("DecodeExtKeyUsage");
|
||||
|
||||
if (GetSequence(input, &idx, &length, sz) < 0) {
|
||||
CYASSL_MSG("\tfail: should be a SEQUENCE\n");
|
||||
CYASSL_MSG("\tfail: should be a SEQUENCE");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
@@ -3366,6 +3630,103 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
|
||||
}
|
||||
|
||||
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
|
||||
{
|
||||
word32 idx = 0;
|
||||
|
||||
(void)heap;
|
||||
|
||||
while (idx < (word32)sz) {
|
||||
int seqLength, strLength;
|
||||
word32 nameIdx;
|
||||
byte b;
|
||||
|
||||
if (GetSequence(input, &idx, &seqLength, sz) < 0) {
|
||||
CYASSL_MSG("\tfail: should be a SEQUENCE");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
nameIdx = idx;
|
||||
b = input[nameIdx++];
|
||||
if (GetLength(input, &nameIdx, &strLength, sz) <= 0) {
|
||||
CYASSL_MSG("\tinvalid length");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE) ||
|
||||
b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE) ||
|
||||
b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) {
|
||||
|
||||
Base_entry* entry = (Base_entry*)XMALLOC(sizeof(Base_entry),
|
||||
heap, DYNAMIC_TYPE_ALTNAME);
|
||||
|
||||
if (entry == NULL) {
|
||||
CYASSL_MSG("allocate error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME);
|
||||
if (entry->name == NULL) {
|
||||
CYASSL_MSG("allocate error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
|
||||
XMEMCPY(entry->name, &input[nameIdx], strLength);
|
||||
entry->nameSz = strLength;
|
||||
entry->type = b & 0x0F;
|
||||
|
||||
entry->next = *head;
|
||||
*head = entry;
|
||||
}
|
||||
|
||||
idx += seqLength;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert)
|
||||
{
|
||||
word32 idx = 0;
|
||||
int length = 0;
|
||||
|
||||
CYASSL_ENTER("DecodeNameConstraints");
|
||||
|
||||
if (GetSequence(input, &idx, &length, sz) < 0) {
|
||||
CYASSL_MSG("\tfail: should be a SEQUENCE");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
while (idx < (word32)sz) {
|
||||
byte b = input[idx++];
|
||||
Base_entry** subtree = NULL;
|
||||
|
||||
if (GetLength(input, &idx, &length, sz) <= 0) {
|
||||
CYASSL_MSG("\tinvalid length");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0))
|
||||
subtree = &cert->permittedNames;
|
||||
else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
|
||||
subtree = &cert->excludedNames;
|
||||
else {
|
||||
CYASSL_MSG("\tinvalid subtree");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
DecodeSubtree(input + idx, length, subtree, cert->heap);
|
||||
|
||||
idx += length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
|
||||
|
||||
#ifdef CYASSL_SEP
|
||||
static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert)
|
||||
{
|
||||
@@ -3552,6 +3913,17 @@ static int DecodeCertExtensions(DecodedCert* cert)
|
||||
return ASN_PARSE_E;
|
||||
break;
|
||||
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
case NAME_CONS_OID:
|
||||
cert->extNameConstraintSet = 1;
|
||||
#ifdef OPENSSL_EXTRA
|
||||
cert->extNameConstraintCrit = critical;
|
||||
#endif
|
||||
if (DecodeNameConstraints(&input[idx], length, cert) < 0)
|
||||
return ASN_PARSE_E;
|
||||
break;
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
|
||||
case INHIBIT_ANY_OID:
|
||||
CYASSL_MSG("Inhibit anyPolicy extension not supported yet.");
|
||||
break;
|
||||
@@ -3714,6 +4086,14 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
|
||||
CYASSL_MSG("Confirm signature failed");
|
||||
return ASN_SIG_CONFIRM_E;
|
||||
}
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
/* check that this cert's name is permitted by the signer's
|
||||
* name constraints */
|
||||
if (!ConfirmNameConstraints(ca, cert)) {
|
||||
CYASSL_MSG("Confirm name constraint failed");
|
||||
return ASN_NAME_INVALID_E;
|
||||
}
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
}
|
||||
else {
|
||||
/* no signer */
|
||||
@@ -3743,6 +4123,10 @@ Signer* MakeSigner(void* heap)
|
||||
signer->publicKey = NULL;
|
||||
signer->nameLen = 0;
|
||||
signer->name = NULL;
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
signer->permittedNames = NULL;
|
||||
signer->excludedNames = NULL;
|
||||
#endif /* IGNORE_NAME_CONSTRAINTS */
|
||||
signer->next = NULL;
|
||||
}
|
||||
(void)heap;
|
||||
@@ -3756,6 +4140,12 @@ void FreeSigner(Signer* signer, void* heap)
|
||||
{
|
||||
XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
|
||||
XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
if (signer->permittedNames)
|
||||
FreeNameSubtrees(signer->permittedNames, heap);
|
||||
if (signer->excludedNames)
|
||||
FreeNameSubtrees(signer->excludedNames, heap);
|
||||
#endif
|
||||
XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
|
||||
|
||||
(void)heap;
|
||||
|
||||
@@ -1299,6 +1299,9 @@ int ecc_make_key(RNG* rng, int keysize, ecc_key* key)
|
||||
{
|
||||
int x, err;
|
||||
|
||||
if (key == NULL || rng == NULL)
|
||||
return ECC_BAD_ARG_E;
|
||||
|
||||
/* find key size */
|
||||
for (x = 0; (keysize > ecc_sets[x].size) && (ecc_sets[x].size != 0); x++)
|
||||
;
|
||||
@@ -1319,12 +1322,22 @@ int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
|
||||
ecc_point* base;
|
||||
mp_int prime;
|
||||
mp_int order;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
byte* buf;
|
||||
#else
|
||||
byte buf[ECC_MAXSIZE];
|
||||
#endif
|
||||
int keysize;
|
||||
|
||||
if (key == NULL || rng == NULL || dp == NULL)
|
||||
return ECC_BAD_ARG_E;
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
buf = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (buf == NULL)
|
||||
return MEMORY_E;
|
||||
#endif
|
||||
|
||||
key->idx = -1;
|
||||
key->dp = dp;
|
||||
keysize = dp->size;
|
||||
@@ -1334,19 +1347,22 @@ int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
|
||||
|
||||
/* make up random string */
|
||||
err = RNG_GenerateBlock(rng, buf, keysize);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
buf[0] |= 0x0c;
|
||||
if (err == 0)
|
||||
buf[0] |= 0x0c;
|
||||
|
||||
/* setup the key variables */
|
||||
if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
|
||||
&key->k, &prime, &order)) != MP_OKAY)
|
||||
return MEMORY_E;
|
||||
if (err == 0) {
|
||||
err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
|
||||
&key->k, &prime, &order);
|
||||
if (err != MP_OKAY)
|
||||
err = MEMORY_E;
|
||||
}
|
||||
|
||||
base = ecc_new_point();
|
||||
if (base == NULL)
|
||||
err = MEMORY_E;
|
||||
if (err == MP_OKAY) {
|
||||
base = ecc_new_point();
|
||||
if (base == NULL)
|
||||
err = MEMORY_E;
|
||||
}
|
||||
|
||||
/* read in the specs for this key */
|
||||
if (err == MP_OKAY)
|
||||
@@ -1384,9 +1400,15 @@ int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
|
||||
ecc_del_point(base);
|
||||
mp_clear(&prime);
|
||||
mp_clear(&order);
|
||||
|
||||
#ifdef ECC_CLEAN_STACK
|
||||
XMEMSET(buff, 0, ECC_MAXSIZE);
|
||||
XMEMSET(buf, 0, ECC_MAXSIZE);
|
||||
#endif
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1750,8 +1772,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA,
|
||||
}
|
||||
}
|
||||
#ifdef ECC_CLEAN_STACK
|
||||
XMEMSET(tA, 0, ECC_BUF_SIZE);
|
||||
XMEMSET(tB, 0, ECC_BUF_SIZE);
|
||||
XMEMSET(tA, 0, ECC_BUFSIZE);
|
||||
XMEMSET(tB, 0, ECC_BUFSIZE);
|
||||
#endif
|
||||
XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(tB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
@@ -1955,7 +1977,11 @@ int ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
|
||||
/* export public ECC key in ANSI X9.63 format */
|
||||
int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
|
||||
{
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
byte* buf;
|
||||
#else
|
||||
byte buf[ECC_BUFSIZE];
|
||||
#endif
|
||||
word32 numlen;
|
||||
int ret = MP_OKAY;
|
||||
|
||||
@@ -1975,25 +2001,37 @@ int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
|
||||
/* store byte 0x04 */
|
||||
out[0] = 0x04;
|
||||
|
||||
/* pad and store x */
|
||||
XMEMSET(buf, 0, sizeof(buf));
|
||||
ret = mp_to_unsigned_bin(&key->pubkey.x,
|
||||
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
|
||||
if (ret != MP_OKAY)
|
||||
return ret;
|
||||
XMEMCPY(out+1, buf, numlen);
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (buf == NULL)
|
||||
return MEMORY_E;
|
||||
#endif
|
||||
|
||||
/* pad and store y */
|
||||
XMEMSET(buf, 0, sizeof(buf));
|
||||
ret = mp_to_unsigned_bin(&key->pubkey.y,
|
||||
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y)));
|
||||
if (ret != MP_OKAY)
|
||||
return ret;
|
||||
XMEMCPY(out+1+numlen, buf, numlen);
|
||||
do {
|
||||
/* pad and store x */
|
||||
XMEMSET(buf, 0, ECC_BUFSIZE);
|
||||
ret = mp_to_unsigned_bin(&key->pubkey.x,
|
||||
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
|
||||
if (ret != MP_OKAY)
|
||||
break;
|
||||
XMEMCPY(out+1, buf, numlen);
|
||||
|
||||
*outLen = 1 + 2*numlen;
|
||||
/* pad and store y */
|
||||
XMEMSET(buf, 0, ECC_BUFSIZE);
|
||||
ret = mp_to_unsigned_bin(&key->pubkey.y,
|
||||
buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y)));
|
||||
if (ret != MP_OKAY)
|
||||
break;
|
||||
XMEMCPY(out+1+numlen, buf, numlen);
|
||||
|
||||
return 0;
|
||||
*outLen = 1 + 2*numlen;
|
||||
} while (0);
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2928,7 +2966,13 @@ static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu)
|
||||
static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
|
||||
mp_digit* mp, int map)
|
||||
{
|
||||
#define KB_SIZE 128
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
unsigned char* kb;
|
||||
#else
|
||||
unsigned char kb[128];
|
||||
#endif
|
||||
int x;
|
||||
unsigned y, z, err, bitlen, bitpos, lut_gap, first;
|
||||
mp_int tk;
|
||||
@@ -2983,71 +3027,88 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
|
||||
lut_gap = bitlen / FP_LUT;
|
||||
|
||||
/* get the k value */
|
||||
if (mp_unsigned_bin_size(&tk) > (int)(sizeof(kb) - 2)) {
|
||||
if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) {
|
||||
mp_clear(&tk);
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
/* store k */
|
||||
XMEMSET(kb, 0, sizeof(kb));
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (kb == NULL)
|
||||
return MEMORY_E;
|
||||
#endif
|
||||
|
||||
XMEMSET(kb, 0, KB_SIZE);
|
||||
if ((err = mp_to_unsigned_bin(&tk, kb)) != MP_OKAY) {
|
||||
mp_clear(&tk);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* let's reverse kb so it's little endian */
|
||||
x = 0;
|
||||
y = mp_unsigned_bin_size(&tk) - 1;
|
||||
mp_clear(&tk);
|
||||
else {
|
||||
/* let's reverse kb so it's little endian */
|
||||
x = 0;
|
||||
y = mp_unsigned_bin_size(&tk) - 1;
|
||||
mp_clear(&tk);
|
||||
|
||||
while ((unsigned)x < y) {
|
||||
z = kb[x]; kb[x] = kb[y]; kb[y] = z;
|
||||
++x; --y;
|
||||
}
|
||||
|
||||
/* at this point we can start, yipee */
|
||||
first = 1;
|
||||
for (x = lut_gap-1; x >= 0; x--) {
|
||||
/* extract FP_LUT bits from kb spread out by lut_gap bits and offset
|
||||
by x bits from the start */
|
||||
bitpos = x;
|
||||
for (y = z = 0; y < FP_LUT; y++) {
|
||||
z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
|
||||
bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
|
||||
the mult in each loop */
|
||||
}
|
||||
|
||||
/* double if not first */
|
||||
if (!first) {
|
||||
if ((err = ecc_projective_dbl_point(R, R, modulus, mp)) != MP_OKAY) {
|
||||
return err;
|
||||
while ((unsigned)x < y) {
|
||||
z = kb[x]; kb[x] = kb[y]; kb[y] = z;
|
||||
++x; --y;
|
||||
}
|
||||
|
||||
/* at this point we can start, yipee */
|
||||
first = 1;
|
||||
for (x = lut_gap-1; x >= 0; x--) {
|
||||
/* extract FP_LUT bits from kb spread out by lut_gap bits and offset
|
||||
by x bits from the start */
|
||||
bitpos = x;
|
||||
for (y = z = 0; y < FP_LUT; y++) {
|
||||
z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
|
||||
bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
|
||||
the mult in each loop */
|
||||
}
|
||||
}
|
||||
|
||||
/* add if not first, otherwise copy */
|
||||
if (!first && z) {
|
||||
if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
|
||||
modulus, mp)) != MP_OKAY) {
|
||||
return err;
|
||||
|
||||
/* double if not first */
|
||||
if (!first) {
|
||||
if ((err = ecc_projective_dbl_point(R, R, modulus,
|
||||
mp)) != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (z) {
|
||||
if ((mp_copy(&fp_cache[idx].LUT[z]->x, &R->x) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx].LUT[z]->y, &R->y) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx].mu, &R->z) != MP_OKAY)) {
|
||||
return GEN_MEM_ERR;
|
||||
|
||||
/* add if not first, otherwise copy */
|
||||
if (!first && z) {
|
||||
if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
|
||||
modulus, mp)) != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
} else if (z) {
|
||||
if ((mp_copy(&fp_cache[idx].LUT[z]->x, &R->x) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx].LUT[z]->y, &R->y) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx].mu, &R->z) != MP_OKAY)) {
|
||||
err = GEN_MEM_ERR;
|
||||
break;
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
z = 0;
|
||||
XMEMSET(kb, 0, sizeof(kb));
|
||||
/* map R back from projective space */
|
||||
if (map) {
|
||||
err = ecc_map(R, modulus, mp);
|
||||
} else {
|
||||
err = MP_OKAY;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == MP_OKAY) {
|
||||
z = 0;
|
||||
XMEMSET(kb, 0, KB_SIZE);
|
||||
/* map R back from projective space */
|
||||
if (map) {
|
||||
err = ecc_map(R, modulus, mp);
|
||||
} else {
|
||||
err = MP_OKAY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
#undef KB_SIZE
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3057,7 +3118,13 @@ static int accel_fp_mul2add(int idx1, int idx2,
|
||||
mp_int* kA, mp_int* kB,
|
||||
ecc_point *R, mp_int* modulus, mp_digit* mp)
|
||||
{
|
||||
#define KB_SIZE 128
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
unsigned char* kb[2];
|
||||
#else
|
||||
unsigned char kb[2][128];
|
||||
#endif
|
||||
int x;
|
||||
unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB;
|
||||
mp_int tka;
|
||||
@@ -3154,18 +3221,25 @@ static int accel_fp_mul2add(int idx1, int idx2,
|
||||
lut_gap = bitlen / FP_LUT;
|
||||
|
||||
/* get the k value */
|
||||
if ((mp_unsigned_bin_size(&tka) > (int)(sizeof(kb[0]) - 2)) ||
|
||||
(mp_unsigned_bin_size(&tkb) > (int)(sizeof(kb[0]) - 2)) ) {
|
||||
if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
|
||||
(mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2)) ) {
|
||||
mp_clear(&tka);
|
||||
mp_clear(&tkb);
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
/* store k */
|
||||
XMEMSET(kb, 0, sizeof(kb));
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (kb[0] == NULL)
|
||||
return MEMORY_E;
|
||||
#endif
|
||||
|
||||
XMEMSET(kb[0], 0, KB_SIZE);
|
||||
if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) {
|
||||
mp_clear(&tka);
|
||||
mp_clear(&tkb);
|
||||
XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3179,80 +3253,101 @@ static int accel_fp_mul2add(int idx1, int idx2,
|
||||
}
|
||||
|
||||
/* store b */
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (kb[1] == NULL) {
|
||||
XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
XMEMSET(kb[1], 0, KB_SIZE);
|
||||
if ((err = mp_to_unsigned_bin(&tkb, kb[1])) != MP_OKAY) {
|
||||
mp_clear(&tkb);
|
||||
return err;
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
y = mp_unsigned_bin_size(&tkb) - 1;
|
||||
mp_clear(&tkb);
|
||||
while ((unsigned)x < y) {
|
||||
z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z;
|
||||
++x; --y;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y = mp_unsigned_bin_size(&tkb) - 1;
|
||||
mp_clear(&tkb);
|
||||
while ((unsigned)x < y) {
|
||||
z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z;
|
||||
++x; --y;
|
||||
}
|
||||
|
||||
/* at this point we can start, yipee */
|
||||
first = 1;
|
||||
for (x = lut_gap-1; x >= 0; x--) {
|
||||
/* extract FP_LUT bits from kb spread out by lut_gap bits and
|
||||
offset by x bits from the start */
|
||||
bitpos = x;
|
||||
for (y = zA = zB = 0; y < FP_LUT; y++) {
|
||||
zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
|
||||
zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
|
||||
bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
|
||||
the mult in each loop */
|
||||
}
|
||||
|
||||
/* double if not first */
|
||||
if (!first) {
|
||||
if ((err = ecc_projective_dbl_point(R, R, modulus, mp)) != MP_OKAY) {
|
||||
return err;
|
||||
/* at this point we can start, yipee */
|
||||
first = 1;
|
||||
for (x = lut_gap-1; x >= 0; x--) {
|
||||
/* extract FP_LUT bits from kb spread out by lut_gap bits and
|
||||
offset by x bits from the start */
|
||||
bitpos = x;
|
||||
for (y = zA = zB = 0; y < FP_LUT; y++) {
|
||||
zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
|
||||
zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
|
||||
bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
|
||||
the mult in each loop */
|
||||
}
|
||||
}
|
||||
|
||||
/* add if not first, otherwise copy */
|
||||
if (!first) {
|
||||
if (zA) {
|
||||
if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
|
||||
R, modulus, mp)) != MP_OKAY) {
|
||||
return err;
|
||||
|
||||
/* double if not first */
|
||||
if (!first) {
|
||||
if ((err = ecc_projective_dbl_point(R, R, modulus,
|
||||
mp)) != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (zB) {
|
||||
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
|
||||
R, modulus, mp)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (zA) {
|
||||
if ((mp_copy(&fp_cache[idx1].LUT[zA]->x, &R->x) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx1].LUT[zA]->y, &R->y) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx1].mu, &R->z) != MP_OKAY)) {
|
||||
return GEN_MEM_ERR;
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
if (zB && first == 0) {
|
||||
if (zB) {
|
||||
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
|
||||
R, modulus, mp)) != MP_OKAY){
|
||||
return err;
|
||||
|
||||
/* add if not first, otherwise copy */
|
||||
if (!first) {
|
||||
if (zA) {
|
||||
if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
|
||||
R, modulus, mp)) != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (zB && first == 1) {
|
||||
if ((mp_copy(&fp_cache[idx2].LUT[zB]->x, &R->x) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx2].LUT[zB]->y, &R->y) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx2].mu, &R->z) != MP_OKAY)) {
|
||||
return GEN_MEM_ERR;
|
||||
}
|
||||
first = 0;
|
||||
if (zB) {
|
||||
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
|
||||
R, modulus, mp)) != MP_OKAY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (zA) {
|
||||
if ((mp_copy(&fp_cache[idx1].LUT[zA]->x, &R->x) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx1].LUT[zA]->y, &R->y) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx1].mu, &R->z) != MP_OKAY)) {
|
||||
err = GEN_MEM_ERR;
|
||||
break;
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
if (zB && first == 0) {
|
||||
if (zB) {
|
||||
if ((err = ecc_projective_add_point(R,
|
||||
fp_cache[idx2].LUT[zB], R, modulus, mp)) != MP_OKAY){
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (zB && first == 1) {
|
||||
if ((mp_copy(&fp_cache[idx2].LUT[zB]->x, &R->x) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx2].LUT[zB]->y, &R->y) != MP_OKAY) ||
|
||||
(mp_copy(&fp_cache[idx2].mu, &R->z) != MP_OKAY)) {
|
||||
err = GEN_MEM_ERR;
|
||||
break;
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
XMEMSET(kb, 0, sizeof(kb));
|
||||
}
|
||||
}
|
||||
|
||||
XMEMSET(kb[0], 0, KB_SIZE);
|
||||
XMEMSET(kb[1], 0, KB_SIZE);
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(kb[1], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
#undef KB_SIZE
|
||||
|
||||
return ecc_map(R, modulus, mp);
|
||||
}
|
||||
@@ -3741,9 +3836,14 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 blockSz;
|
||||
word32 digestSz;
|
||||
ecEncCtx localCtx;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
byte* sharedSecret;
|
||||
byte* keys;
|
||||
#else
|
||||
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
||||
byte keys[ECC_BUFSIZE]; /* max size */
|
||||
word32 sharedSz = sizeof(sharedSecret);
|
||||
#endif
|
||||
word32 sharedSz = ECC_MAXSIZE;
|
||||
int keysLen;
|
||||
int encKeySz;
|
||||
int ivSz;
|
||||
@@ -3782,7 +3882,7 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
|
||||
}
|
||||
|
||||
if (keysLen > (int)sizeof(keys))
|
||||
if (keysLen > ECC_BUFSIZE) /* keys size */
|
||||
return BUFFER_E;
|
||||
|
||||
if ( (msgSz%blockSz) != 0)
|
||||
@@ -3791,70 +3891,90 @@ int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
if (*outSz < (msgSz + digestSz))
|
||||
return BUFFER_E;
|
||||
|
||||
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (sharedSecret == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
switch (ctx->kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
||||
ctx->kdfSaltSz, ctx->kdfInfo,
|
||||
ctx->kdfInfoSz, keys, keysLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (keys == NULL) {
|
||||
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
||||
|
||||
if (ret == 0) {
|
||||
switch (ctx->kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
||||
ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
|
||||
keys, keysLen);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
encKey = keys + offset;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
if (ret == 0) {
|
||||
encKey = keys + offset;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
|
||||
switch (ctx->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_ENCRYPTION);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = AesCbcEncrypt(&aes, out, msg, msgSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
switch (ctx->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
ret = AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
|
||||
AES_ENCRYPTION);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = AesCbcEncrypt(&aes, out, msg, msgSz);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ctx->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
Hmac hmac;
|
||||
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = HmacUpdate(&hmac, out, msgSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = HmacFinal(&hmac, out+msgSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
if (ret == 0) {
|
||||
switch (ctx->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
Hmac hmac;
|
||||
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = HmacUpdate(&hmac, out, msgSz);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = HmacFinal(&hmac, out+msgSz);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*outSz = msgSz + digestSz;
|
||||
if (ret == 0)
|
||||
*outSz = msgSz + digestSz;
|
||||
|
||||
return 0;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -3868,9 +3988,14 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
word32 blockSz;
|
||||
word32 digestSz;
|
||||
ecEncCtx localCtx;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
byte* sharedSecret;
|
||||
byte* keys;
|
||||
#else
|
||||
byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
||||
byte keys[ECC_BUFSIZE]; /* max size */
|
||||
word32 sharedSz = sizeof(sharedSecret);
|
||||
#endif
|
||||
word32 sharedSz = ECC_MAXSIZE;
|
||||
int keysLen;
|
||||
int encKeySz;
|
||||
int ivSz;
|
||||
@@ -3909,7 +4034,7 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
|
||||
}
|
||||
|
||||
if (keysLen > (int)sizeof(keys))
|
||||
if (keysLen > ECC_BUFSIZE) /* keys size */
|
||||
return BUFFER_E;
|
||||
|
||||
if ( ((msgSz-digestSz) % blockSz) != 0)
|
||||
@@ -3918,75 +4043,95 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
if (*outSz < (msgSz - digestSz))
|
||||
return BUFFER_E;
|
||||
|
||||
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (sharedSecret == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
switch (ctx->kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
||||
ctx->kdfSaltSz, ctx->kdfInfo,
|
||||
ctx->kdfInfoSz, keys, keysLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
break;
|
||||
keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (keys == NULL) {
|
||||
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
||||
|
||||
if (ret == 0) {
|
||||
switch (ctx->kdfAlgo) {
|
||||
case ecHKDF_SHA256 :
|
||||
ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
||||
ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
|
||||
keys, keysLen);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
encKey = keys + offset;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
if (ret == 0) {
|
||||
encKey = keys + offset;
|
||||
encIv = encKey + encKeySz;
|
||||
macKey = encKey + encKeySz + ivSz;
|
||||
|
||||
switch (ctx->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
byte verify[SHA256_DIGEST_SIZE];
|
||||
Hmac hmac;
|
||||
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = HmacUpdate(&hmac, msg, msgSz-digestSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = HmacFinal(&hmac, verify);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
switch (ctx->macAlgo) {
|
||||
case ecHMAC_SHA256:
|
||||
{
|
||||
byte verify[SHA256_DIGEST_SIZE];
|
||||
Hmac hmac;
|
||||
ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = HmacUpdate(&hmac, msg, msgSz-digestSz);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = HmacFinal(&hmac, verify);
|
||||
if (ret != 0)
|
||||
break;
|
||||
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ctx->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
ret = AesSetKey(&aes, encKey,KEY_SIZE_128,encIv,AES_DECRYPTION);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
if (ret == 0) {
|
||||
switch (ctx->encAlgo) {
|
||||
case ecAES_128_CBC:
|
||||
{
|
||||
Aes aes;
|
||||
ret = AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
|
||||
AES_DECRYPTION);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
default:
|
||||
ret = BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*outSz = msgSz - digestSz;
|
||||
if (ret == 0)
|
||||
*outSz = msgSz - digestSz;
|
||||
|
||||
return 0;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -351,6 +351,10 @@ void CTaoCryptErrorString(int error, char* buffer)
|
||||
XSTRNCPY(buffer, "FIPS mode not allowed error", max);
|
||||
break;
|
||||
|
||||
case ASN_NAME_INVALID_E:
|
||||
XSTRNCPY(buffer, "Name Constraint error", max);
|
||||
break;
|
||||
|
||||
default:
|
||||
XSTRNCPY(buffer, "unknown error number", max);
|
||||
|
||||
|
||||
@@ -338,6 +338,7 @@ static INLINE int DoProcess(HC128* ctx, byte* output, const byte* input,
|
||||
|
||||
if (msglen > 0)
|
||||
{
|
||||
XMEMSET(keystream, 0, sizeof(keystream)); /* hush the static analysis */
|
||||
generate_keystream(ctx, keystream);
|
||||
|
||||
#ifdef BIG_ENDIAN_ORDER
|
||||
|
||||
@@ -585,11 +585,7 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
||||
byte* content = NULL;
|
||||
byte* sig = NULL;
|
||||
byte* cert = NULL;
|
||||
byte* signedAttr = NULL;
|
||||
int contentSz = 0, sigSz = 0, certSz = 0, signedAttrSz = 0;
|
||||
|
||||
(void)signedAttr; /* not used yet, just set */
|
||||
(void)signedAttrSz;
|
||||
int contentSz = 0, sigSz = 0, certSz = 0;
|
||||
|
||||
if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
|
||||
return BAD_FUNC_ARG;
|
||||
@@ -750,10 +746,6 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
||||
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* save pointer and length */
|
||||
signedAttr = &pkiMsg[idx];
|
||||
signedAttrSz = length;
|
||||
|
||||
idx += length;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,16 +33,15 @@
|
||||
#include <cyassl/ctaocrypt/random.h>
|
||||
#include <cyassl/ctaocrypt/error-crypt.h>
|
||||
|
||||
#ifdef NO_RC4
|
||||
#if defined(HAVE_HASHDRBG) || defined(NO_RC4)
|
||||
#include <cyassl/ctaocrypt/sha256.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <cyassl/ctaocrypt/misc.h>
|
||||
#else
|
||||
#define MISC_DUMM_FUNC misc_dummy_random
|
||||
#include <ctaocrypt/src/misc.c>
|
||||
#endif
|
||||
#endif
|
||||
#endif /* HAVE_HASHDRBG || NO_RC4 */
|
||||
|
||||
#if defined(USE_WINDOWS_API)
|
||||
#ifndef _WIN32_WINNT
|
||||
@@ -63,32 +62,36 @@
|
||||
#endif /* USE_WINDOWS_API */
|
||||
|
||||
|
||||
#ifdef NO_RC4
|
||||
#if defined(HAVE_HASHDRBG) || defined(NO_RC4)
|
||||
|
||||
/* Start NIST DRBG code */
|
||||
|
||||
#define OUTPUT_BLOCK_LEN (256/8)
|
||||
#define MAX_REQUEST_LEN (0x1000)
|
||||
#define MAX_STRING_LEN (0x100000000)
|
||||
#define RESEED_MAX (0x100000000000LL)
|
||||
#define ENTROPY_SZ 256
|
||||
#define OUTPUT_BLOCK_LEN (SHA256_DIGEST_SIZE)
|
||||
#define MAX_REQUEST_LEN (0x10000)
|
||||
#define RESEED_INTERVAL (1000000)
|
||||
#define SECURITY_STRENGTH (256)
|
||||
#define ENTROPY_SZ (SECURITY_STRENGTH/8)
|
||||
#define NONCE_SZ (ENTROPY_SZ/2)
|
||||
#define ENTROPY_NONCE_SZ (ENTROPY_SZ+NONCE_SZ)
|
||||
|
||||
#define DBRG_SUCCESS 0
|
||||
#define DBRG_ERROR 1
|
||||
#define DBRG_NEED_RESEED 2
|
||||
#define DRBG_SUCCESS 0
|
||||
#define DRBG_ERROR 1
|
||||
#define DRBG_NEED_RESEED 2
|
||||
|
||||
|
||||
enum {
|
||||
dbrgInitC = 0,
|
||||
dbrgReseed = 1,
|
||||
dbrgGenerateW = 2,
|
||||
dbrgGenerateH = 3,
|
||||
dbrgInitV
|
||||
drbgInitC = 0,
|
||||
drbgReseed = 1,
|
||||
drbgGenerateW = 2,
|
||||
drbgGenerateH = 3,
|
||||
drbgInitV
|
||||
};
|
||||
|
||||
|
||||
static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type, byte* inA, word32 inASz,
|
||||
byte* inB, word32 inBSz, byte* inC, word32 inCSz)
|
||||
static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type,
|
||||
byte* inA, word32 inASz,
|
||||
byte* inB, word32 inBSz,
|
||||
byte* inC, word32 inCSz)
|
||||
{
|
||||
byte ctr;
|
||||
int i;
|
||||
@@ -98,60 +101,60 @@ static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type, byte* inA, word
|
||||
#ifdef LITTLE_ENDIAN_ORDER
|
||||
bits = ByteReverseWord32(bits);
|
||||
#endif
|
||||
len = (outSz / SHA256_DIGEST_SIZE)
|
||||
+ ((outSz % SHA256_DIGEST_SIZE) ? 1 : 0);
|
||||
len = (outSz / OUTPUT_BLOCK_LEN)
|
||||
+ ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
|
||||
|
||||
for (i = 0, ctr = 1; i < len; i++, ctr++)
|
||||
{
|
||||
if (InitSha256(&rng->sha) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
if (Sha256Update(&rng->sha, &ctr, sizeof(ctr)) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
if (Sha256Update(&rng->sha, (byte*)&bits, sizeof(bits)) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
/* churning V is the only string that doesn't have
|
||||
* the type added */
|
||||
if (type != dbrgInitV)
|
||||
if (type != drbgInitV)
|
||||
if (Sha256Update(&rng->sha, &type, sizeof(type)) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
if (Sha256Update(&rng->sha, inA, inASz) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
if (inB != NULL && inBSz > 0)
|
||||
if (Sha256Update(&rng->sha, inB, inBSz) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
if (inC != NULL && inCSz > 0)
|
||||
if (Sha256Update(&rng->sha, inC, inCSz) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
if (Sha256Final(&rng->sha, rng->digest) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
if (outSz > SHA256_DIGEST_SIZE) {
|
||||
XMEMCPY(out, rng->digest, SHA256_DIGEST_SIZE);
|
||||
outSz -= SHA256_DIGEST_SIZE;
|
||||
out += SHA256_DIGEST_SIZE;
|
||||
if (outSz > OUTPUT_BLOCK_LEN) {
|
||||
XMEMCPY(out, rng->digest, OUTPUT_BLOCK_LEN);
|
||||
outSz -= OUTPUT_BLOCK_LEN;
|
||||
out += OUTPUT_BLOCK_LEN;
|
||||
}
|
||||
else {
|
||||
XMEMCPY(out, rng->digest, outSz);
|
||||
}
|
||||
}
|
||||
|
||||
return DBRG_SUCCESS;
|
||||
return DRBG_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int Hash_DBRG_Reseed(RNG* rng, byte* entropy, word32 entropySz)
|
||||
static int Hash_DRBG_Reseed(RNG* rng, byte* entropy, word32 entropySz)
|
||||
{
|
||||
int ret;
|
||||
byte seed[DBRG_SEED_LEN];
|
||||
byte seed[DRBG_SEED_LEN];
|
||||
|
||||
ret = Hash_df(rng, seed, sizeof(seed), dbrgInitV, rng->V, sizeof(rng->V),
|
||||
ret = Hash_df(rng, seed, sizeof(seed), drbgReseed, rng->V, sizeof(rng->V),
|
||||
entropy, entropySz, NULL, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@@ -159,12 +162,12 @@ static int Hash_DBRG_Reseed(RNG* rng, byte* entropy, word32 entropySz)
|
||||
XMEMCPY(rng->V, seed, sizeof(rng->V));
|
||||
XMEMSET(seed, 0, sizeof(seed));
|
||||
|
||||
ret = Hash_df(rng, rng->C, sizeof(rng->C), dbrgInitC, rng->V,
|
||||
ret = Hash_df(rng, rng->C, sizeof(rng->C), drbgInitC, rng->V,
|
||||
sizeof(rng->V), NULL, 0, NULL, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
rng->reseed_ctr = 1;
|
||||
rng->reseedCtr = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -181,10 +184,10 @@ static INLINE void array_add_one(byte* data, word32 dataSz)
|
||||
|
||||
static int Hash_gen(RNG* rng, byte* out, word32 outSz, byte* V)
|
||||
{
|
||||
byte data[DBRG_SEED_LEN];
|
||||
byte data[DRBG_SEED_LEN];
|
||||
int i, ret;
|
||||
int len = (outSz / SHA256_DIGEST_SIZE)
|
||||
+ ((outSz % SHA256_DIGEST_SIZE) ? 1 : 0);
|
||||
int len = (outSz / OUTPUT_BLOCK_LEN)
|
||||
+ ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
|
||||
|
||||
XMEMCPY(data, V, sizeof(data));
|
||||
for (i = 0; i < len; i++) {
|
||||
@@ -200,11 +203,11 @@ static int Hash_gen(RNG* rng, byte* out, word32 outSz, byte* V)
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (outSz > SHA256_DIGEST_SIZE) {
|
||||
XMEMCPY(out, rng->digest, SHA256_DIGEST_SIZE);
|
||||
outSz -= SHA256_DIGEST_SIZE;
|
||||
out += SHA256_DIGEST_SIZE;
|
||||
array_add_one(data, DBRG_SEED_LEN);
|
||||
if (outSz > OUTPUT_BLOCK_LEN) {
|
||||
XMEMCPY(out, rng->digest, OUTPUT_BLOCK_LEN);
|
||||
outSz -= OUTPUT_BLOCK_LEN;
|
||||
out += OUTPUT_BLOCK_LEN;
|
||||
array_add_one(data, DRBG_SEED_LEN);
|
||||
}
|
||||
else {
|
||||
XMEMCPY(out, rng->digest, outSz);
|
||||
@@ -235,66 +238,71 @@ static INLINE void array_add(byte* d, word32 dLen, byte* s, word32 sLen)
|
||||
}
|
||||
|
||||
|
||||
static int Hash_DBRG_Generate(RNG* rng, byte* out, word32 outSz)
|
||||
static int Hash_DRBG_Generate(RNG* rng, byte* out, word32 outSz)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (rng->reseed_ctr != RESEED_MAX) {
|
||||
byte type = dbrgGenerateH;
|
||||
if (rng->reseedCtr != RESEED_INTERVAL) {
|
||||
byte type = drbgGenerateH;
|
||||
word32 reseedCtr = rng->reseedCtr;
|
||||
|
||||
rng->reseedCtr++;
|
||||
if (Hash_gen(rng, out, outSz, rng->V) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
if (InitSha256(&rng->sha) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
if (Sha256Update(&rng->sha, &type, sizeof(type)) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
if (Sha256Update(&rng->sha, rng->V, sizeof(rng->V)) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
if (Sha256Final(&rng->sha, rng->digest) != 0)
|
||||
return DBRG_ERROR;
|
||||
return DRBG_ERROR;
|
||||
|
||||
array_add(rng->V, sizeof(rng->V), rng->digest, sizeof(rng->digest));
|
||||
array_add(rng->V, sizeof(rng->V), rng->C, sizeof(rng->C));
|
||||
array_add(rng->V, sizeof(rng->V),
|
||||
(byte*)&rng->reseed_ctr, sizeof(rng->reseed_ctr));
|
||||
rng->reseed_ctr++;
|
||||
ret = DBRG_SUCCESS;
|
||||
#ifdef LITTLE_ENDIAN_ORDER
|
||||
reseedCtr = ByteReverseWord32(reseedCtr);
|
||||
#endif
|
||||
array_add(rng->V, sizeof(rng->V), (byte*)&reseedCtr, sizeof(reseedCtr));
|
||||
ret = DRBG_SUCCESS;
|
||||
}
|
||||
else {
|
||||
ret = DBRG_NEED_RESEED;
|
||||
ret = DRBG_NEED_RESEED;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int Hash_DBRG_Instantiate(RNG* rng, byte* seed, word32 seedSz)
|
||||
static int Hash_DRBG_Instantiate(RNG* rng, byte* seed, word32 seedSz,
|
||||
byte* nonce, word32 nonceSz, byte* personal, word32 personalSz)
|
||||
{
|
||||
int ret;
|
||||
|
||||
XMEMSET(rng, 0, sizeof(*rng));
|
||||
ret = Hash_df(rng, rng->V, sizeof(rng->V), dbrgInitV, seed, seedSz, NULL, 0,
|
||||
NULL, 0);
|
||||
ret = Hash_df(rng, rng->V, sizeof(rng->V), drbgInitV, seed, seedSz,
|
||||
nonce, nonceSz, personal, personalSz);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = Hash_df(rng, rng->C, sizeof(rng->C), dbrgInitC, rng->V,
|
||||
ret = Hash_df(rng, rng->C, sizeof(rng->C), drbgInitC, rng->V,
|
||||
sizeof(rng->V), NULL, 0, NULL, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
rng->reseed_ctr = 1;
|
||||
rng->reseedCtr = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int Hash_DBRG_Uninstantiate(RNG* rng)
|
||||
static int Hash_DRBG_Uninstantiate(RNG* rng)
|
||||
{
|
||||
int result = DBRG_ERROR;
|
||||
int result = DRBG_ERROR;
|
||||
|
||||
if (rng != NULL) {
|
||||
XMEMSET(rng, 0, sizeof(*rng));
|
||||
result = DBRG_SUCCESS;
|
||||
result = DRBG_SUCCESS;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -303,17 +311,21 @@ static int Hash_DBRG_Uninstantiate(RNG* rng)
|
||||
/* End NIST DRBG Code */
|
||||
|
||||
|
||||
|
||||
/* Get seed and key cipher */
|
||||
int InitRng(RNG* rng)
|
||||
{
|
||||
byte entropy[ENTROPY_SZ];
|
||||
int ret = DBRG_ERROR;
|
||||
byte entropy[ENTROPY_NONCE_SZ];
|
||||
int ret = DRBG_ERROR;
|
||||
|
||||
if (GenerateSeed(&rng->seed, entropy, sizeof(entropy)) == 0)
|
||||
ret = Hash_DBRG_Instantiate(rng, entropy, sizeof(entropy));
|
||||
/* This doesn't use a separate nonce. The entropy input will be
|
||||
* the default size plus the size of the nonce making the seed
|
||||
* size. */
|
||||
if (GenerateSeed(&rng->seed, entropy, ENTROPY_NONCE_SZ) == 0)
|
||||
ret = Hash_DRBG_Instantiate(rng, entropy, ENTROPY_NONCE_SZ,
|
||||
NULL, 0, NULL, 0);
|
||||
|
||||
XMEMSET(entropy, 0, ENTROPY_NONCE_SZ);
|
||||
|
||||
XMEMSET(entropy, 0, sizeof(entropy));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -324,20 +336,22 @@ int RNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
|
||||
int ret;
|
||||
|
||||
XMEMSET(output, 0, sz);
|
||||
ret = Hash_DBRG_Generate(rng, output, sz);
|
||||
ret = Hash_DRBG_Generate(rng, output, sz);
|
||||
|
||||
if (ret == DBRG_NEED_RESEED) {
|
||||
if (ret == DRBG_NEED_RESEED) {
|
||||
byte entropy[ENTROPY_SZ];
|
||||
ret = GenerateSeed(&rng->seed, entropy, sizeof(entropy));
|
||||
|
||||
ret = GenerateSeed(&rng->seed, entropy, ENTROPY_SZ);
|
||||
if (ret == 0) {
|
||||
ret = Hash_DBRG_Reseed(rng, entropy, sizeof(entropy));
|
||||
ret = Hash_DRBG_Reseed(rng, entropy, ENTROPY_SZ);
|
||||
|
||||
if (ret == 0)
|
||||
ret = Hash_DBRG_Generate(rng, output, sz);
|
||||
ret = Hash_DRBG_Generate(rng, output, sz);
|
||||
}
|
||||
else
|
||||
ret = DBRG_ERROR;
|
||||
XMEMSET(entropy, 0, sizeof(entropy));
|
||||
ret = DRBG_ERROR;
|
||||
|
||||
XMEMSET(entropy, 0, ENTROPY_SZ);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -352,30 +366,53 @@ int RNG_GenerateByte(RNG* rng, byte* b)
|
||||
|
||||
void FreeRng(RNG* rng)
|
||||
{
|
||||
Hash_DBRG_Uninstantiate(rng);
|
||||
Hash_DRBG_Uninstantiate(rng);
|
||||
}
|
||||
|
||||
#else /* NO_RC4 */
|
||||
#else /* HAVE_HASHDRBG || NO_RC4 */
|
||||
|
||||
/* Get seed and key cipher */
|
||||
int InitRng(RNG* rng)
|
||||
{
|
||||
int ret;
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
byte* key;
|
||||
byte* junk;
|
||||
#else
|
||||
byte key[32];
|
||||
byte junk[256];
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CAVIUM
|
||||
if (rng->magic == CYASSL_RNG_CAVIUM_MAGIC)
|
||||
return 0;
|
||||
#endif
|
||||
ret = GenerateSeed(&rng->seed, key, sizeof(key));
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (key == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
junk = (byte*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (junk == NULL) {
|
||||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = GenerateSeed(&rng->seed, key, 32);
|
||||
|
||||
if (ret == 0) {
|
||||
Arc4SetKey(&rng->cipher, key, sizeof(key));
|
||||
|
||||
return RNG_GenerateBlock(rng, junk, sizeof(junk)); /*rid initial state*/
|
||||
ret = RNG_GenerateBlock(rng, junk, 256); /*rid initial state*/
|
||||
}
|
||||
|
||||
#ifdef CYASSL_SMALL_STACK
|
||||
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(junk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -446,7 +483,7 @@ static void CaviumRNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
|
||||
|
||||
#endif /* HAVE_CAVIUM */
|
||||
|
||||
#endif /* NO_RC4 */
|
||||
#endif /* HAVE_HASHDRBG || NO_RC4 */
|
||||
|
||||
|
||||
#if defined(USE_WINDOWS_API)
|
||||
|
||||
@@ -95,7 +95,7 @@ void s_fp_add(fp_int *a, fp_int *b, fp_int *c)
|
||||
register fp_word t;
|
||||
|
||||
y = MAX(a->used, b->used);
|
||||
oldused = c->used;
|
||||
oldused = MAX(c->used, FP_SIZE); /* help static analysis w/ max size */
|
||||
c->used = y;
|
||||
|
||||
t = 0;
|
||||
|
||||
Reference in New Issue
Block a user