Upgrade libtomcrypt

This commit is contained in:
2025-10-24 19:33:21 +03:00
parent d770dd8df3
commit acc69bb8ad
157 changed files with 922 additions and 761 deletions

View File

@@ -39,7 +39,7 @@ const int der_asn1_type_to_identifier_map[] =
24, /* LTC_ASN1_GENERALIZEDTIME, */
-1, /* LTC_ASN1_CUSTOM_TYPE, */
};
const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]);
const unsigned long der_asn1_type_to_identifier_map_sz = LTC_ARRAY_SIZE(der_asn1_type_to_identifier_map);
/**
A Map from the ASN.1 Class to its string
@@ -51,7 +51,7 @@ const char* der_asn1_class_to_string_map[] =
"CONTEXT-SPECIFIC",
"PRIVATE",
};
const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]);
const unsigned long der_asn1_class_to_string_map_sz = LTC_ARRAY_SIZE(der_asn1_class_to_string_map);
/**
A Map from the ASN.1 P/C-bit to its string
@@ -61,7 +61,7 @@ const char* der_asn1_pc_to_string_map[] =
"PRIMITIVE",
"CONSTRUCTED",
};
const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]);
const unsigned long der_asn1_pc_to_string_map_sz = LTC_ARRAY_SIZE(der_asn1_pc_to_string_map);
/**
A Map from the ASN.1 tag to its string
@@ -106,7 +106,7 @@ const char* der_asn1_tag_to_string_map[] =
"OID internationalized resource identifier type",
"Relative OID internationalized resource identifier type",
};
const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]);
const unsigned long der_asn1_tag_to_string_map_sz = LTC_ARRAY_SIZE(der_asn1_tag_to_string_map);
/**
A Map from ASN.1 Tags to ltc_asn1_type
@@ -152,6 +152,6 @@ const ltc_asn1_type der_asn1_tag_to_type_map[] =
/* 30 */
LTC_ASN1_CUSTOM_TYPE, /* BMPString types */
};
const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]);
const unsigned long der_asn1_tag_to_type_map_sz = LTC_ARRAY_SIZE(der_asn1_tag_to_type_map);
#endif

View File

@@ -47,7 +47,7 @@ static const unsigned char tag_constructed_map[] =
LTC_ASN1_PC_PRIMITIVE,
LTC_ASN1_PC_PRIMITIVE,
};
static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]);
static const unsigned long tag_constructed_map_sz = LTC_ARRAY_SIZE(tag_constructed_map);
/**
Decode the ASN.1 Identifier

View File

@@ -119,7 +119,7 @@ static const struct {
int der_ia5_char_encode(int c)
{
int x;
for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
for (x = 0; x < (int)LTC_ARRAY_SIZE(ia5_table); x++) {
if (ia5_table[x].code == c) {
return ia5_table[x].value;
}
@@ -130,7 +130,7 @@ int der_ia5_char_encode(int c)
int der_ia5_value_decode(int v)
{
int x;
for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
for (x = 0; x < (int)LTC_ARRAY_SIZE(ia5_table); x++) {
if (ia5_table[x].value == v) {
return ia5_table[x].code;
}

View File

@@ -27,7 +27,7 @@ int der_encode_object_identifier(const unsigned long *words, unsigned long nwor
LTC_ARGCHK(outlen != NULL);
/* check length */
if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) {
if ((err = der_length_object_identifier_full(words, nwords, &x, &z)) != CRYPT_OK) {
return err;
}
if (x > *outlen) {
@@ -35,17 +35,6 @@ int der_encode_object_identifier(const unsigned long *words, unsigned long nwor
return CRYPT_BUFFER_OVERFLOW;
}
/* compute length to store OID data */
z = 0;
wordbuf = words[0] * 40 + words[1];
for (y = 1; y < nwords; y++) {
t = der_object_identifier_bits(wordbuf);
z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
if (y < nwords - 1) {
wordbuf = words[y + 1];
}
}
/* store header + length */
x = 0;
out[x++] = 0x06;
@@ -59,7 +48,7 @@ int der_encode_object_identifier(const unsigned long *words, unsigned long nwor
wordbuf = words[0] * 40 + words[1];
for (i = 1; i < nwords; i++) {
/* store 7 bit words in little endian */
t = wordbuf & 0xFFFFFFFF;
t = wordbuf;
if (t) {
y = x;
mask = 0;

View File

@@ -9,27 +9,24 @@
#ifdef LTC_DER
unsigned long der_object_identifier_bits(unsigned long x)
static LTC_INLINE unsigned long s_der_object_identifier_bits(unsigned long x)
{
#if defined(LTC_HAVE_CLZL_BUILTIN)
if (x == 0)
return 0;
return sizeof(unsigned long) * CHAR_BIT - __builtin_clzl(x);
#else
unsigned long c;
x &= 0xFFFFFFFF;
c = 0;
while (x) {
++c;
x >>= 1;
}
return c;
#endif
}
/**
Gets length of DER encoding of Object Identifier
@param nwords The number of OID words
@param words The actual OID words to get the size of
@param outlen [out] The length of the DER encoding for the given string
@return CRYPT_OK if successful
*/
int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen)
int der_length_object_identifier_full(const unsigned long *words, unsigned long nwords, unsigned long *outlen, unsigned long *datalen)
{
unsigned long y, z, t, wordbuf;
@@ -51,7 +48,7 @@ int der_length_object_identifier(const unsigned long *words, unsigned long nword
z = 0;
wordbuf = words[0] * 40 + words[1];
for (y = 1; y < nwords; y++) {
t = der_object_identifier_bits(wordbuf);
t = s_der_object_identifier_bits(wordbuf);
z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
if (y < nwords - 1) {
/* grab next word */
@@ -59,6 +56,9 @@ int der_length_object_identifier(const unsigned long *words, unsigned long nword
}
}
if (datalen) {
*datalen = z;
}
/* now depending on the length our length encoding changes */
if (z < 128) {
z += 2;
@@ -74,4 +74,16 @@ int der_length_object_identifier(const unsigned long *words, unsigned long nword
return CRYPT_OK;
}
/**
Gets length of DER encoding of Object Identifier
@param nwords The number of OID words
@param words The actual OID words to get the size of
@param outlen [out] The length of the DER encoding for the given string
@return CRYPT_OK if successful
*/
int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen)
{
return der_length_object_identifier_full(words, nwords, outlen, NULL);
}
#endif

View File

@@ -91,7 +91,7 @@ static const struct {
int der_printable_char_encode(int c)
{
int x;
for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
for (x = 0; x < (int)LTC_ARRAY_SIZE(printable_table); x++) {
if (printable_table[x].code == c) {
return printable_table[x].value;
}
@@ -102,7 +102,7 @@ int der_printable_char_encode(int c)
int der_printable_value_decode(int v)
{
int x;
for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
for (x = 0; x < (int)LTC_ARRAY_SIZE(printable_table); x++) {
if (printable_table[x].value == v) {
return printable_table[x].code;
}

View File

@@ -31,6 +31,22 @@ static int s_new_element(ltc_asn1_list **l)
}
return CRYPT_OK;
}
#if defined(LTC_TEST_DBG)
void s_print_err(const char *errstr, ltc_asn1_list *l, int err, unsigned long identifier, unsigned long data_offset, unsigned long len)
{
#if LTC_TEST_DBG <= 1
if (err == CRYPT_OK)
return;
#endif
if (l->type == LTC_ASN1_CUSTOM_TYPE) {
fprintf(stderr, "%s %02lx: hl=%4lu l=%4lu - %s[%s %llu] (%s)\n", errstr, identifier, data_offset, len, der_asn1_class_to_string_map[l->klass], der_asn1_pc_to_string_map[l->pc], l->tag, error_to_string(err));
} else {
fprintf(stderr, "%s %02lx: hl=%4lu l=%4lu - %s (%s)\n", errstr, identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
}
}
#else
#define s_print_err(errstr, l, err, identifier, data_offset, len) LTC_UNUSED_PARAM(data_offset)
#endif
/**
ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
@@ -43,7 +59,8 @@ static int s_new_element(ltc_asn1_list **l)
static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth)
{
ltc_asn1_list *l;
unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
int err;
unsigned long identifier, len, totlen, data_offset, id_len, len_len;
void *realloc_tmp;
LTC_ARGCHK(in != NULL);
@@ -77,30 +94,19 @@ static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *i
if (l->type != LTC_ASN1_EOL) {
/* fetch length */
len_len = *inlen - id_len;
#if defined(LTC_TEST_DBG)
/* init with dummy values for error cases */
data_offset = 666;
len = 0;
#endif
if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
#if defined(LTC_TEST_DBG)
fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
#endif
s_print_err("E1", l, err, identifier, data_offset, len);
goto error;
} else if (len > (*inlen - id_len - len_len)) {
err = CRYPT_INVALID_PACKET;
#if defined(LTC_TEST_DBG)
fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
#endif
s_print_err("E2", l, err, identifier, data_offset, len);
goto error;
}
data_offset = id_len + len_len;
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
if (l->type == LTC_ASN1_CUSTOM_TYPE && l->klass == LTC_ASN1_CL_CONTEXT_SPECIFIC) {
fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag);
} else {
fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]);
}
#endif
s_print_err("OK", l, err, identifier, data_offset, len);
len += data_offset;
if (l->type == LTC_ASN1_CUSTOM_TYPE) {

View File

@@ -135,7 +135,7 @@ static const struct {
int der_teletex_char_encode(int c)
{
int x;
for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) {
for (x = 0; x < (int)LTC_ARRAY_SIZE(teletex_table); x++) {
if (teletex_table[x].code == c) {
return teletex_table[x].value;
}
@@ -146,7 +146,7 @@ int der_teletex_char_encode(int c)
int der_teletex_value_decode(int v)
{
int x;
for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) {
for (x = 0; x < (int)LTC_ARRAY_SIZE(teletex_table); x++) {
if (teletex_table[x].value == v) {
return teletex_table[x].code;
}

View File

@@ -66,7 +66,7 @@ int pk_get_oid_id(enum ltc_pka_id pka, enum ltc_oid_id *oid)
{
unsigned int i;
LTC_ARGCHK(oid != NULL);
for (i = 1; i < sizeof(pka_oids)/sizeof(pka_oids[0]); ++i) {
for (i = 1; i < LTC_ARRAY_SIZE(pka_oids); ++i) {
if (pka_oids[i].pka == pka) {
*oid = pka_oids[i].id;
return CRYPT_OK;
@@ -95,7 +95,7 @@ int pk_get_oid_from_asn1(const ltc_asn1_list *oid, enum ltc_oid_id *id)
return err;
}
for (i = 1; i < sizeof(pka_oids)/sizeof(pka_oids[0]); ++i) {
for (i = 1; i < LTC_ARRAY_SIZE(pka_oids); ++i) {
if (XSTRCMP(pka_oids[i].oid, tmp) == 0) {
*id = pka_oids[i].id;
return CRYPT_OK;

View File

@@ -10,20 +10,18 @@
int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen)
{
unsigned long i, j, limit, oid_j;
size_t OID_len;
LTC_ARGCHK(oidlen != NULL);
limit = *oidlen;
*oidlen = 0; /* make sure that we return zero oidlen on error */
for (i = 0; i < limit; i++) oid[i] = 0;
if (oid != NULL) {
XMEMSET(oid, 0, sizeof(*oid) * limit);
}
if (OID == NULL) return CRYPT_OK;
if (OID[0] == '\0') return CRYPT_OK;
OID_len = XSTRLEN(OID);
if (OID_len == 0) return CRYPT_OK;
for (i = 0, j = 0; i < OID_len; i++) {
for (i = 0, j = 0; OID[i] != '\0'; i++) {
if (OID[i] == '.') {
if (++j >= limit) continue;
}
@@ -38,50 +36,75 @@ int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen
}
}
if (j == 0) return CRYPT_ERROR;
if (j >= limit) {
*oidlen = j;
*oidlen = j + 1;
if (j >= limit || oid == NULL) {
return CRYPT_BUFFER_OVERFLOW;
}
*oidlen = j + 1;
return CRYPT_OK;
}
typedef struct num_to_str {
int err;
char *wr;
unsigned long max_len, res_len;
} num_to_str;
static LTC_INLINE void s_wr(char c, num_to_str *w)
{
if (w->res_len == ULONG_MAX) {
w->err = CRYPT_OVERFLOW;
return;
}
w->res_len++;
if (w->res_len > w->max_len) w->wr = NULL;
if (w->wr) w->wr[w->max_len - w->res_len] = c;
}
int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen)
{
int i;
unsigned long j, k;
char tmp[LTC_OID_MAX_STRLEN] = { 0 };
num_to_str w;
unsigned long j;
LTC_ARGCHK(oid != NULL);
LTC_ARGCHK(oidlen < INT_MAX);
LTC_ARGCHK(outlen != NULL);
for (i = oidlen - 1, k = 0; i >= 0; i--) {
if (OID == NULL || *outlen == 0) {
w.max_len = ULONG_MAX;
w.wr = NULL;
} else {
w.max_len = *outlen;
w.wr = OID;
}
w.res_len = 0;
w.err = CRYPT_OK;
s_wr('\0', &w);
for (i = oidlen; i --> 0;) {
j = oid[i];
if (j == 0) {
tmp[k] = '0';
if (++k >= sizeof(tmp)) return CRYPT_ERROR;
}
else {
s_wr('0', &w);
} else {
while (j > 0) {
tmp[k] = '0' + (j % 10);
if (++k >= sizeof(tmp)) return CRYPT_ERROR;
s_wr('0' + (j % 10), &w);
j /= 10;
}
}
if (i > 0) {
tmp[k] = '.';
if (++k >= sizeof(tmp)) return CRYPT_ERROR;
s_wr('.', &w);
}
}
if (*outlen < k + 1) {
*outlen = k + 1;
if (w.err != CRYPT_OK) {
return w.err;
}
if (*outlen < w.res_len || OID == NULL) {
*outlen = w.res_len;
return CRYPT_BUFFER_OVERFLOW;
}
LTC_ARGCHK(OID != NULL);
for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1];
OID[k] = '\0';
*outlen = k; /* the length without terminating NUL byte */
XMEMMOVE(OID, OID + (w.max_len - w.res_len), w.res_len);
*outlen = w.res_len;
return CRYPT_OK;
}

View File

@@ -70,7 +70,7 @@ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long i
}
/* this includes the internal hash ID and optional params (NULL in this case) */
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, LTC_ARRAY_SIZE(tmpoid));
if (parameters_type == LTC_ASN1_EOL) {
alg_id_num = 1;
} else {

View File

@@ -47,7 +47,7 @@ int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outle
return err;
}
oidlen = sizeof(oid)/sizeof(oid[0]);
oidlen = LTC_ARRAY_SIZE(oid);
if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) {
return err;
}
@@ -56,7 +56,7 @@ int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outle
LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
return der_encode_sequence_multi(out, outlen,
LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id,
LTC_ASN1_SEQUENCE, (unsigned long)LTC_ARRAY_SIZE(alg_id), alg_id,
LTC_ASN1_RAW_BIT_STRING, public_key_len*8U, public_key,
LTC_ASN1_EOL, 0UL, NULL);

View File

@@ -40,7 +40,7 @@ int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
}
/* decode to find out hash */
LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, LTC_ARRAY_SIZE(hashOID));
err = der_decode_sequence(in, inlen, decode, 1);
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
return err;

View File

@@ -93,7 +93,7 @@ static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int mo
#endif
hash = -1;
for (i = 0; i < sizeof(accepted_hashes)/sizeof(accepted_hashes[0]); ++i) {
for (i = 0; i < LTC_ARRAY_SIZE(accepted_hashes); ++i) {
hash = find_hash(accepted_hashes[i]);
if (hash != -1) break;
}

View File

@@ -46,7 +46,7 @@ int ec25519_export( unsigned char *out, unsigned long *outlen,
if ((err = pk_get_oid(oid_id, &OID)) != CRYPT_OK) {
return err;
}
oidlen = sizeof(oid)/sizeof(oid[0]);
oidlen = LTC_ARRAY_SIZE(oid);
if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) {
return err;
}

View File

@@ -41,7 +41,7 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
}
/* decode to find out hash */
LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, LTC_ARRAY_SIZE(hashOID));
err = der_decode_sequence(in, inlen, decode, 1);
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
return err;

View File

@@ -90,7 +90,7 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons
}
*/
oidlen = sizeof(oid)/sizeof(oid[0]);
oidlen = LTC_ARRAY_SIZE(oid);
if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) {
goto error;
}

View File

@@ -59,6 +59,7 @@ int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key)
goto error;
}
key->type = PK_PRIVATE;
key->rfc6979_hash_alg = NULL;
/* success */
err = CRYPT_OK;

View File

@@ -0,0 +1,162 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file ecc_rfc6979_key.c
ECC Crypto, Russ Williams
*/
#ifdef LTC_MECC
#ifdef LTC_SHA256
/**
Make deterministic ECC key using the RFC6979 method
@param priv [in] Private key for HMAC
@param in Message to sign for HMAC
@param inlen Length of the message
@param key [out] Newly created deterministic key
@return CRYPT_OK if successful, upon error all allocated memory will be freed
*/
int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long inlen, ecc_key *key)
{
int err, hash = -1;
unsigned char v[MAXBLOCKSIZE], k[MAXBLOCKSIZE];
unsigned char buffer[256], sep[1], privkey[128];
unsigned long order_bits, len_diff, pk_len, zero_extend, outlen, klen, vlen, buflen, qlen, hashsize;
void *r, *d;
LTC_ARGCHK(ltc_mp.name != NULL);
LTC_ARGCHK(priv != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(key->dp.size > 0);
if (priv->rfc6979_hash_alg == NULL) {
return CRYPT_INVALID_ARG;
}
hash = find_hash(priv->rfc6979_hash_alg);
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
hashsize = hash_descriptor[hash].hashsize;
if ((err = ltc_mp_init_multi(&r, &d, NULL)) != CRYPT_OK) {
return err;
}
/* Length, in bytes, of key */
order_bits = ltc_mp_count_bits(key->dp.order);
qlen = (order_bits+7) >> 3;
len_diff = qlen > inlen ? qlen - inlen : 0;
pk_len = (ltc_mp_count_bits(priv->k)+7) >> 3;
zero_extend = qlen - pk_len;
XMEMSET(buffer, 0x00, len_diff + zero_extend);
/* RFC6979 3.2b, set V */
XMEMSET(v, 0x01, hashsize);
/* RFC6979 3.2c, set K */
XMEMSET(k, 0x00, hashsize);
if ((err = ltc_mp_to_unsigned_bin(priv->k, privkey) != CRYPT_OK)) { goto error; }
/* RFC6979 3.2d, set K to HMAC_K(V::0x00::priv::in) */
sep[0] = 0;
klen = sizeof(k);
if((err = hmac_memory_multi(hash,
k, hashsize,
k, &klen,
v, hashsize,
sep, 1,
buffer, zero_extend,
privkey, qlen - zero_extend,
buffer, len_diff,
in, qlen - len_diff,
LTC_NULL)) != CRYPT_OK) { goto error; }
/* RFC6979 3.2e, set V = HMAC_K(V) */
vlen = sizeof(v);
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &vlen)) != CRYPT_OK) { goto error; }
/* RFC6979 3.2f, set K to HMAC_K(V::0x01::priv::in) */
sep[0] = 0x01;
outlen = sizeof(k);
if((err = hmac_memory_multi(hash,
k, klen,
k, &klen,
v, hashsize,
sep, 1,
buffer, zero_extend,
privkey, qlen - zero_extend,
buffer, len_diff,
in, qlen - len_diff,
LTC_NULL)) != CRYPT_OK) { goto error; }
/* RFC6979 3.2g, set V = HMAC_K(V) */
outlen = sizeof(v);
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; }
/* RFC6979 3.2h, generate and check key */
do {
/* concatenate hash bits into T */
buflen = 0;
while (buflen < qlen) {
if (buflen + hashsize >= sizeof(buffer) || buflen + hashsize < buflen) {
err = CRYPT_BUFFER_OVERFLOW;
goto error;
}
outlen = sizeof(v);
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(&buffer[buflen], v, hashsize);
buflen += hashsize;
}
/* key->k = bits2int(T) */
if ((err = ltc_mp_read_unsigned_bin(r, buffer, qlen)) != CRYPT_OK) { goto error; }
if ((qlen * 8) > order_bits) {
if ((err = ltc_mp_2expt(d, (qlen * 8) - order_bits)) != CRYPT_OK) { goto error; }
if ((err = ltc_mp_div(r, d, r, NULL)) != CRYPT_OK) { goto error; }
if ((err = ltc_mp_to_unsigned_bin(r, buffer)) != CRYPT_OK) { goto error; }
qlen = ltc_mp_unsigned_bin_size(r);
}
if ((err = ecc_set_key(buffer, qlen, PK_PRIVATE, key))!= CRYPT_OK) { goto error; }
/* check that k is in range [1,q-1] */
if (ltc_mp_cmp_d(key->k, 0) == LTC_MP_GT && ltc_mp_cmp(key->k, key->dp.order) == LTC_MP_LT) {
/* Check that pubkey.x != 0 (mod p) */
if ((err = ltc_mp_mod(key->pubkey.x, key->dp.order, r)) != CRYPT_OK) { goto error; }
/* if we have a valid key, exit loop */
if (ltc_mp_iszero(r) == LTC_MP_NO)
break;
} else {
/* K = HMAC_K(V::0x00) */
buffer[0] = 0x0;
outlen = sizeof(k);
if((err = hmac_memory_multi(hash, k, klen, k, &klen, v, hashsize, buffer, 1, LTC_NULL)) != CRYPT_OK) { goto error; }
/* V = HMAC_K(V) */
outlen = sizeof(v);
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; }
/* ... and try again! */
}
} while (1);
key->type = PK_PRIVATE;
/* success */
err = CRYPT_OK;
goto cleanup;
error:
ecc_free(key);
cleanup:
ltc_mp_cleanup_multi(&d, &r, NULL);
return err;
}
#endif
#endif

View File

@@ -23,6 +23,8 @@ int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key)
return err;
}
key->rfc6979_hash_alg = NULL;
/* A, B, order, prime, Gx, Gy */
if ((err = ltc_mp_read_radix(key->dp.prime, cu->prime, 16)) != CRYPT_OK) { goto error; }
if ((err = ltc_mp_read_radix(key->dp.order, cu->order, 16)) != CRYPT_OK) { goto error; }

View File

@@ -33,7 +33,7 @@ int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key
else if (type == PK_PUBLIC) {
/* load public key */
if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; }
if ((err = ltc_mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
if ((err = ltc_mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
}
else {
err = CRYPT_INVALID_PACKET;
@@ -46,6 +46,7 @@ int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key
}
key->type = type;
key->rfc6979_hash_alg = NULL;
return CRYPT_OK;
error:

View File

@@ -57,8 +57,12 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen,
/* make up a key and export the public copy */
do {
if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; }
if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; }
if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; }
if (key->rfc6979_hash_alg != NULL) {
if ((err = ecc_rfc6979_key(key, in, inlen, &pubkey)) != CRYPT_OK) { goto errnokey; }
} else {
if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; }
}
/* find r = x1 mod n */
if ((err = ltc_mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
@@ -78,7 +82,7 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen,
if (ltc_mp_iszero(r) == LTC_MP_YES) {
ecc_free(&pubkey);
} else {
if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */
if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */
/* find s = (e + xr)/k */
if ((err = ltc_mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */
if ((err = ltc_mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */

View File

@@ -19,7 +19,7 @@
*/
int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key)
{
char oidstr[64] = {0};
char oidstr[LTC_OID_MAX_STRLEN] = {0};
unsigned long oidlen = sizeof(oidstr);
int err, size = 0;

View File

@@ -24,7 +24,7 @@ static void s_mpi_shrink_multi(void **a, ...)
cur = a;
va_start(args, a);
while (cur != NULL) {
if (n >= sizeof(tmp)/sizeof(tmp[0])) {
if (n >= LTC_ARRAY_SIZE(tmp)) {
goto out;
}
if (*cur != NULL) {
@@ -49,8 +49,8 @@ out:
* or after this was called with too many args
*/
if ((err != CRYPT_OK) ||
(n >= sizeof(tmp)/sizeof(tmp[0]))) {
for (n = 0; n < sizeof(tmp)/sizeof(tmp[0]); ++n) {
(n >= LTC_ARRAY_SIZE(tmp))) {
for (n = 0; n < LTC_ARRAY_SIZE(tmp); ++n) {
if (tmp[n] != NULL) {
ltc_mp_clear(tmp[n]);
}

View File

@@ -131,7 +131,7 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle
hash OCTET STRING
}
*/
LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));
LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, LTC_ARRAY_SIZE(loid));
LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);