Upgrade libtomcrypt
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
162
Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_rfc6979_key.c
Normal file
162
Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_rfc6979_key.c
Normal 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
|
||||
@@ -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; }
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user