From 381bfb5b99778fe9026b6d5462dd36a52fd6628b Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 27 Feb 2022 19:09:39 +0800 Subject: [PATCH] Update src --- src/aes_modes.c | 2 +- src/asn1.c | 474 +++++-- src/block_cipher.c | 2 + src/chacha20.c | 6 +- src/cms.c | 2551 +++------------------------------- src/debug.c | 13 + src/digest.c | 80 +- src/gf128.c | 6 +- src/hash_drbg.c | 12 +- src/hkdf.c | 2 +- src/hmac.c | 14 +- src/oid.c | 361 +---- src/pem.c | 2 +- src/pkcs8.c | 95 +- src/rc4.c | 16 +- src/sm2_algo.c | 4 +- src/sm2_asn1.c | 116 +- src/sm2_lib.c | 31 +- src/sm2_prn.c | 62 +- src/sm4_modes.c | 2 +- src/sm9_math.c | 3 +- src/version.c | 11 +- src/x509_alg.c | 634 +++++++++ src/x509_algor.c | 508 ------- src/x509_asn1.c | 1424 ------------------- src/x509_cer.c | 1229 +++++++++++++++++ src/x509_crl.c | 808 ++++++----- src/x509_ext.c | 3302 +++++++++++++++----------------------------- src/x509_lib.c | 240 ---- src/x509_oid.c | 444 ++++++ src/x509_prn.c | 511 +++++++ src/x509_req.c | 383 +++++ src/x509_str.c | 272 ++++ src/zuc_core.c | 46 +- src/zuc_eea.c | 10 +- src/zuc_eia.c | 16 +- 36 files changed, 5884 insertions(+), 7808 deletions(-) create mode 100644 src/x509_alg.c delete mode 100644 src/x509_algor.c delete mode 100644 src/x509_asn1.c create mode 100644 src/x509_cer.c delete mode 100644 src/x509_lib.c create mode 100644 src/x509_oid.c create mode 100644 src/x509_prn.c create mode 100644 src/x509_req.c create mode 100644 src/x509_str.c diff --git a/src/aes_modes.c b/src/aes_modes.c index 70d805a2..ad10b134 100644 --- a/src/aes_modes.c +++ b/src/aes_modes.c @@ -161,7 +161,7 @@ void aes_ctr_encrypt(const AES_KEY *key, uint8_t ctr[16], const uint8_t *in, siz int aes_gcm_encrypt(const AES_KEY *key, const uint8_t *iv, size_t ivlen, const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, - uint8_t *out, const size_t taglen, uint8_t *tag) + uint8_t *out, size_t taglen, uint8_t *tag) { const uint8_t *pin = in; uint8_t *pout = out; diff --git a/src/asn1.c b/src/asn1.c index bb99dfb7..256d483f 100644 --- a/src/asn1.c +++ b/src/asn1.c @@ -59,6 +59,9 @@ #include "endian.h" +//FIXME: ENUMERATED 没有支持,在CRLReason中用到 + + /* ## 返回值 @@ -131,7 +134,7 @@ const char *asn1_tag_name(int tag) return NULL; } -static int asn1_tag_is_cstring(int tag) +int asn1_tag_is_cstring(int tag) { switch (tag) { case ASN1_TAG_UTF8String: @@ -167,15 +170,16 @@ int asn1_ia5_string_check(const char *a, size_t alen) // 还是检查报错比较方便,这样调用的函数更容易实现 // asn.1编解码不考虑效率的问题 -void asn1_tag_to_der(int tag, uint8_t **out, size_t *outlen) +int asn1_tag_to_der(int tag, uint8_t **out, size_t *outlen) { if (out) { *(*out)++ = (uint8_t)tag; } (*outlen)++; + return 1; } -void asn1_length_to_der(size_t len, uint8_t **out, size_t *outlen) +int asn1_length_to_der(size_t len, uint8_t **out, size_t *outlen) { if (len < 128) { if (out) { @@ -200,15 +204,18 @@ void asn1_length_to_der(size_t len, uint8_t **out, size_t *outlen) } (*outlen) += 1 + i; } + return 1; } -void asn1_data_to_der(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) +// 提供返回值是为了和其他to_der函数一致 +int asn1_data_to_der(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) { if (out) { memcpy(*out, data, datalen); *out += datalen; } *outlen += datalen; + return 1; } int asn1_tag_from_der(int tag, const uint8_t **in, size_t *inlen) @@ -226,6 +233,15 @@ int asn1_tag_from_der(int tag, const uint8_t **in, size_t *inlen) return 1; } +int asn1_tag_get(int *tag, const uint8_t **in, size_t *inlen) +{ + if (*inlen == 0) { + return 0; + } + *tag = **in; + return 1; +} + int asn1_length_from_der(size_t *plen, const uint8_t **pin, size_t *pinlen) { const uint8_t *in = *pin; @@ -332,27 +348,6 @@ int asn1_type_from_der(int tag, const uint8_t **data, size_t *datalen, const uin return 1; } -int asn1_type_copy_from_der(int tag, size_t maxlen, uint8_t *data, size_t *datalen, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *p; - - if ((ret = asn1_tag_from_der(tag, in, inlen)) != 1) { - return ret; - } - if (asn1_length_from_der(datalen, in, inlen) != 1 - || asn1_data_from_der(&p, *datalen, in, inlen) != 1) { - error_print(); - return -1; - } - if (*datalen > maxlen) { - error_print(); - return -1; - } - memcpy(data, p, *datalen); - return 1; -} - int asn1_any_tag_from_der(int *tag, const uint8_t **in, size_t *inlen) { if (*inlen == 0) { @@ -381,6 +376,11 @@ int asn1_any_type_from_der(int *tag, const uint8_t **data, size_t *datalen, cons return 1; } +int asn1_any_to_der(const uint8_t *tlv, size_t tlvlen, uint8_t **out, size_t *outlen) +{ + return asn1_data_to_der(tlv, tlvlen, out, outlen); +} + int asn1_any_from_der(const uint8_t **tlv, size_t *tlvlen, const uint8_t **in, size_t *inlen) { int ret; @@ -400,6 +400,9 @@ int asn1_any_from_der(const uint8_t **tlv, size_t *tlvlen, const uint8_t **in, s ////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define ASN1_TRUE 0xff +#define ASN1_FALSE 0x00 + int asn1_boolean_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen) { if ((out && !(*out)) || !outlen) { @@ -497,6 +500,12 @@ int asn1_bit_string_to_der_ex(int tag, const uint8_t *bits, size_t nbits, uint8_ return 1; } +int asn1_bit_octets_to_der_ex(int tag, const uint8_t *octs, size_t nocts, uint8_t **out, size_t *outlen) +{ + return asn1_bit_string_to_der_ex(tag, octs, nocts << 3, out, outlen); +} + + int asn1_bits_to_der_ex(int tag, int bits, uint8_t **out, size_t *outlen) { size_t nbits = 0; @@ -534,7 +543,122 @@ int asn1_null_to_der(uint8_t **out, size_t *outlen) return 1; } -int asn1_object_identifier_to_der_ex(int tag, int oid, const uint32_t *nodes, size_t nodes_count, uint8_t **out, size_t *outlen) +static void asn1_oid_node_to_base128(uint32_t a, uint8_t **out, size_t *outlen) +{ + uint8_t buf[5]; + int n = 0; + + buf[n++] = a & 0x7f; + a >>= 7; + + while (a) { + buf[n++] = 0x80 | (a & 0x7f); + a >>= 7; + } + + while (n--) { + if (out) + *(*out)++ = buf[n]; + (*outlen)++; + } +} + +// 实际上我们在解析的时候是不知道具体在哪里结束的 +// 解析是有可能出错的,如果没有发现最后一个0开头的字节就出错了 +// 还有值太大也会出错,我们最多读取5个字节 +// { 0x81, 0x82 } +// { 0x81, 0x82, 0x83, 0x84, 0x85, 0x06 } +static int asn1_oid_node_from_base128(uint32_t *a, const uint8_t **in, size_t *inlen) +{ + uint8_t buf[5]; + int n = 0; + int i; + + for (;;) { + if ((*inlen)-- < 1 || n >= 5) { + return -1; + } + buf[n] = *(*in)++; + if ((buf[n++] & 0x80) == 0) { + break; + } + } + + // 32 - 7*4 = 4, so the first byte should be like 1000bbbb + if (n == 5 && (buf[0] & 0x70)) { + return -1; + } + + *a = 0; + for (i = 0; i < n; i++) { + *a = ((*a) << 7) | (buf[i] & 0x7f); + } + + return 1; +} + +int asn1_oid_nodes_to_octets(const uint32_t *nodes, size_t nodes_cnt, uint8_t *out, size_t *outlen) +{ + if (nodes_cnt < 2 || nodes_cnt > 32) { + return -1; + } + if (out) + *out++ = (uint8_t)(nodes[0] * 40 + nodes[1]); + (*outlen) = 1; + nodes += 2; + nodes_cnt -= 2; + + while (nodes_cnt--) { + asn1_oid_node_to_base128(*nodes++, &out, outlen); + } + return 1; +} + +// 因为这个函数总是被asn1函数调用的,因此给的输入数据长度是已知的 +int asn1_object_identifier_from_octets(uint32_t *nodes, size_t *nodes_cnt, const uint8_t *in, size_t inlen) +{ + size_t count = 0; + const uint8_t *p = in; + size_t len = inlen; + + if (!nodes || !nodes_cnt || !in || inlen <= 0) { + error_print(); + return -1; + } + + if (inlen < 1) { + error_print(); + return -1; + } + + // FIXME: 需要支持 nodes = NULL 吗? + if (nodes) { + *nodes++ = (*in) / 40; + *nodes++ = (*in) % 40; + } + in++; + inlen--; + count += 2; + + while (inlen) { + uint32_t val; + if (count > 32) { + return -1; + } + if (asn1_oid_node_from_base128(&val, &in, &inlen) < 0) { + return -1; + } + if (nodes) { + *nodes++ = val; + } + count++; + } + + *nodes_cnt = count; + return 1; +} + +int asn1_object_identifier_to_der_ex(int tag, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen) { uint8_t octets[32]; size_t octetslen = 0; @@ -547,9 +671,7 @@ int asn1_object_identifier_to_der_ex(int tag, int oid, const uint32_t *nodes, si *(*out)++ = tag; (*outlen)++; - if (oid != OID_undef) - asn1_oid_to_octets(oid, octets, &octetslen); - else asn1_oid_nodes_to_octets(nodes, nodes_count, octets, &octetslen); + asn1_oid_nodes_to_octets(nodes, nodes_cnt, octets, &octetslen); asn1_length_to_der(octetslen, out, outlen); @@ -562,19 +684,94 @@ int asn1_object_identifier_to_der_ex(int tag, int oid, const uint32_t *nodes, si return 1; } -int asn1_utf8_string_to_der_ex(int tag, const char *a, uint8_t **out, size_t *outlen) +const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t count, const char *name) { - return asn1_type_to_der(tag, (const uint8_t *)a, strlen(a), out, outlen); + size_t i; + for (i = 0; i < count; i++) { + if (strcmp(infos[i].name, name) == 0) { + return &infos[i]; + } + } + return NULL; } -int asn1_printable_string_to_der_ex(int tag, const char *a, uint8_t **out, size_t *outlen) +const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t count, int oid) { - return asn1_type_to_der(tag, (const uint8_t *)a, strlen(a), out, outlen); + size_t i; + for (i = 0; i < count; i++) { + if (infos[i].oid == oid) { + return &infos[i]; + } + } + return NULL; } -int asn1_ia5_string_to_der_ex(int tag, const char *a, uint8_t **out, size_t *outlen) +// 这个函数可以支持未知的OID,通常只有在print或者解析Extensions时需要调用该函数 +// 注意:函数有特殊返回值 +int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_t *nodes_cnt, + const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen) { - return asn1_type_to_der(tag, (const uint8_t *)a, strlen(a), out, outlen); + int ret; + size_t i; + + if ((ret = asn1_object_identifier_from_der(nodes, nodes_cnt, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + *info = NULL; + for (i = 0; i < count; i++) { + if (*nodes_cnt == infos[i].nodes_cnt + && memcmp(nodes, infos[i].nodes, (*nodes_cnt) * sizeof(int)) == 0) { + *info = &infos[i]; + return 1; + } + } + return 2; // 返回非1的正整数表示OID格式正确但是不在给定列表中 +} + +int asn1_oid_info_from_der(const ASN1_OID_INFO **info, const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen) +{ + int ret; + uint32_t nodes[32]; + size_t nodes_cnt; + + if ((ret = asn1_oid_info_from_der_ex(info, nodes, &nodes_cnt, infos, count, in, inlen)) < 0) { + error_print(); + return -1; + } else if (ret > 1) { + error_print(); + return -1; + } + return ret; +} + + +// asn1_oid_from_octets 不返回错误值,只返回 OID_undef +// 但是数据编码仍可能是非法的 +// 如果返回 OID_undef,需要通过 asn1_object_identifier_from_octets 判断格式是否正确 + +// 显然这个函数并不合适,因为在整个gmssl中,我们不提供完整的ASN.1数据库,无法从一个OID中给出解析 + + + + + + + + +int asn1_utf8_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + return asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen); +} + +int asn1_printable_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + return asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen); +} + +int asn1_ia5_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + return asn1_type_to_der(tag, (const uint8_t *)d, dlen, out, outlen); } int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen) @@ -792,6 +989,23 @@ int asn1_bit_string_from_der_ex(int tag, const uint8_t **bits, size_t *nbits, co return 1; } +int asn1_bit_octets_from_der_ex(int tag, const uint8_t **octs, size_t *nocts, const uint8_t **in, size_t *inlen) +{ + int ret; + size_t nbits; + + if ((ret = asn1_bit_string_from_der_ex(tag, octs, &nbits, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (nbits % 8) { + error_print(); + return -1; + } + *nocts = nbits >> 3; + return 1; +} + int asn1_bits_from_der_ex(int tag, int *bits, const uint8_t **in, size_t *inlen) { int ret; @@ -836,15 +1050,14 @@ int asn1_null_from_der(const uint8_t **in, size_t *inlen) return 1; } -// FIXME:这个函数应该最终取消返回oid -int asn1_object_identifier_from_der_ex(int tag, int *oid, uint32_t nodes[32], size_t *nodes_count, +int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **pin, size_t *pinlen) { const uint8_t *in = *pin; size_t inlen = *pinlen; size_t len; - if (!nodes || !nodes_count || !pin || !(*pin) || !pinlen) { + if (!nodes || !nodes_cnt || !pin || !(*pin) || !pinlen) { error_print(); return -1; } @@ -858,14 +1071,10 @@ int asn1_object_identifier_from_der_ex(int tag, int *oid, uint32_t nodes[32], si error_print(); return -1; } - // 由于 asn1_oid_from_der 无法判断不识别的 OID 数据编码是否正确,因此必须先解码 - if (asn1_oid_nodes_from_octets(nodes, nodes_count, in, len) < 0) { + if (asn1_object_identifier_from_octets(nodes, nodes_cnt, in, len) != 1) { error_print(); return -1; } - if (oid) { - *oid = asn1_oid_from_octets(in, len); - } *pin = in + len; *pinlen = inlen - len; return 1; @@ -1015,47 +1224,6 @@ int asn1_generalized_time_from_der_ex(int tag, time_t *t, const uint8_t **pin, s return 1; } -// 其中的每一个data/datalen都是一个ASN1的TLV,因此我们可以去解析 -int asn1_sequence_of_get_next_item(const ASN1_SEQUENCE_OF *a, const uint8_t **next, const uint8_t **data, size_t *datalen) -{ - int ret; - size_t len; - int tag; - const uint8_t *value; - size_t valuelen; - - if (*next == NULL) { - *next = a->data; - } - if (*next < a->data || *next > a->data + a->datalen) { - error_print(); - return -1; - } - *data = *next; - len = a->data + a->datalen - *next; - ret = asn1_any_type_from_der(&tag, &value, &valuelen, next, &len); - if (ret < 0) error_print(); - *datalen = *next - *data; - return ret; -} - -int asn1_sequence_of_get_count(const ASN1_SEQUENCE_OF *a, size_t *count) -{ - int ret; - const uint8_t *next = NULL; - const uint8_t *data; - size_t datalen; - - *count = 0; - while ((ret = asn1_sequence_of_get_next_item(a, &next, &data, &datalen)) == 1) { - (*count)++; - } - if (ret < 0) { - error_print(); - return -1; - } - return 1; -} int asn1_check(int expr) { @@ -1068,8 +1236,146 @@ int asn1_check(int expr) int asn1_length_is_zero(size_t len) { if (len) { + error_print(); + return -1; + } + return 1; +} + +int asn1_length_le(size_t len1, size_t len2) +{ + if (len1 > len2) { + error_print(); + return -1; + } + return 1; +} + +int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt) +{ + if (a_cnt != b_cnt + || memcmp(a, b, b_cnt * sizeof(uint32_t)) != 0) { error_print(); return 0; } return 1; } + + +int asn1_sequence_of_int_to_der(const int *nums, size_t nums_cnt, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + size_t i; + for (i = 0; i < nums_cnt; i++) { + if (asn1_int_to_der(nums[i], NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < nums_cnt; i++) { + if (asn1_int_to_der(nums[i], out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int asn1_sequence_of_int_from_der(int *nums, size_t *nums_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + *nums_cnt = 0; + while (dlen) { + int num; + if (asn1_int_from_der(&num, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (nums) { + *nums++ = num; + } + (*nums_cnt)++; + } + return 1; +} + +int asn1_sequence_of_int_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return -1; +} + + +int asn1_object_identifier_print(FILE *fp, int format, int indent, const char *label, const char *name, + const uint32_t *nodes, size_t nodes_cnt) +{ + size_t i; + format_print(fp, format, indent, "%s: %s (", label, name); + for (i = 0; i < nodes_cnt - 1; i++) { + fprintf(fp, "%d.", (int)nodes[i]); + } + fprintf(fp, "%d)\n", nodes[i]); + return 1; +} + +int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen) +{ + format_print(fp, fmt, ind, "%s: ", label); + while (dlen--) { + fprintf(fp, "%c", *d++); + } + fprintf(fp, "\n"); + return 1; +} + +int asn1_bits_print(FILE *fp, int fmt, int ind, const char *label, const char **names, size_t names_cnt, int bits) +{ + size_t i; + format_print(fp, fmt, ind, "%s: ", label); + + for (i = 0; i < names_cnt; i++) { + if (bits & 0x01) + fprintf(fp, "%s", names[i]); + bits >>= 1; + if (bits) + fprintf(fp, ", "); + } + fprintf(fp, "\n"); + if (bits) { + error_print(); + return -1; + } + return 1; +} + + +int asn1_types_get_count(const uint8_t *d, size_t dlen, int tag, size_t *cnt) +{ + error_print(); + return -1; +} + +int asn1_types_get_item_by_index(const uint8_t *d, size_t *dlen, int tag, + int index, const uint8_t **item_d, size_t *item_dlen) +{ + error_print(); + return -1; +} + + + + + + + + diff --git a/src/block_cipher.c b/src/block_cipher.c index 042d61de..b6ca65bf 100644 --- a/src/block_cipher.c +++ b/src/block_cipher.c @@ -85,6 +85,7 @@ int block_cipher_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *in, uint8_t } static const BLOCK_CIPHER sm4_block_cipher_object = { + OID_sm4, SM4_KEY_SIZE, SM4_BLOCK_SIZE, (block_cipher_set_encrypt_key_func)sm4_set_encrypt_key, @@ -106,6 +107,7 @@ static int aes128_set_decrypt_key(AES_KEY *aes_key, const uint8_t key[16]) { } static const BLOCK_CIPHER aes128_block_cipher_object = { + OID_aes128, AES128_KEY_SIZE, AES_BLOCK_SIZE, (block_cipher_set_encrypt_key_func)aes128_set_encrypt_key, diff --git a/src/chacha20.c b/src/chacha20.c index 5b3cccce..aef45d03 100644 --- a/src/chacha20.c +++ b/src/chacha20.c @@ -54,8 +54,8 @@ #include "endian.h" void chacha20_set_key(CHACHA20_STATE *state, - const unsigned char key[CHACHA20_KEY_SIZE], - const unsigned char nonce[CHACHA20_NONCE_SIZE], + const uint8_t key[CHACHA20_KEY_SIZE], + const uint8_t nonce[CHACHA20_NONCE_SIZE], uint32_t counter) { state->d[ 0] = 0x61707865; @@ -102,7 +102,7 @@ void chacha20_set_key(CHACHA20_STATE *state, QR(S[2], S[7], S[ 8], S[13]); \ QR(S[3], S[4], S[ 9], S[14]) -void chacha20_generate_keystream(CHACHA20_STATE *state, unsigned int counts, unsigned char *out) +void chacha20_generate_keystream(CHACHA20_STATE *state, size_t counts, uint8_t *out) { uint32_t working_state[16]; int i; diff --git a/src/cms.c b/src/cms.c index 24b4bce1..8a422cce 100644 --- a/src/cms.c +++ b/src/cms.c @@ -56,82 +56,106 @@ #include #include #include +#include +#include +#include #include #include -// 这个是干什么用的? -int find_cert(X509_CERTIFICATE *cert, - const uint8_t *certs, size_t certslen, - const X509_NAME *issuer, const uint8_t *serial_number, size_t serial_number_len) + + +static uint32_t oid_cms_data[] = { oid_sm2_cms,1 }; +static uint32_t oid_cms_signed_data[] = { oid_sm2_cms,2 }; +static uint32_t oid_cms_enveloped_data[] = { oid_sm2_cms,3 }; +static uint32_t oid_cms_signed_and_enveloped_data[] = { oid_sm2_cms,4 }; +static uint32_t oid_cms_encrypted_data[] = { oid_sm2_cms,5 }; +static uint32_t oid_cms_key_agreement_info[] = { oid_sm2_cms,6 }; + +static const ASN1_OID_INFO cms_content_types[] = { + { OID_cms_data, "data", oid_cms_data, sizeof(oid_cms_data)/sizeof(int) }, + { OID_cms_signed_data, "signedData", oid_cms_signed_data, sizeof(oid_cms_signed_data)/sizeof(int) }, + { OID_cms_enveloped_data, "envelopedData", oid_cms_signed_data, sizeof(oid_cms_signed_data)/sizeof(int) }, + { OID_cms_signed_and_enveloped_data, "signedAndEnvelopedData", oid_cms_signed_and_enveloped_data, sizeof(oid_cms_signed_and_enveloped_data)/sizeof(int) }, + { OID_cms_encrypted_data, "encryptedData", oid_cms_encrypted_data, sizeof(oid_cms_encrypted_data)/sizeof(int) }, + { OID_cms_key_agreement_info, "keyAgreementInfo", oid_cms_key_agreement_info, sizeof(oid_cms_key_agreement_info)/sizeof(int) } +}; + +static const size_t cms_content_types_count = + sizeof(cms_content_types)/sizeof(cms_content_types[0]); + +const char *cms_content_type_name(int oid) { - - while (certslen) { - if (x509_certificate_from_der(cert, &certs, &certslen) != 1) { - error_print(); - return -1; - } - - if (x509_name_equ(issuer, &cert->tbs_certificate.issuer) - && serial_number_len == cert->tbs_certificate.serial_number_len - && memcmp(serial_number, cert->tbs_certificate.serial_number, serial_number_len) == 0) { - return 1; - } + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(cms_content_types, cms_content_types_count, oid))) { + error_print(); + return NULL; } - - return 0; + return info->name; } - - -/* -data ::= OCTET STRING -*/ - -int cms_data_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent) +int cms_content_type_from_name(const char *name) { - const uint8_t *data; - size_t datalen; + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(cms_content_types, cms_content_types_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} - if (asn1_octet_string_from_der(&data, &datalen, &a, &alen) != 1) { +int cms_content_type_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(cms_content_types, cms_content_types_count, oid))) { error_print(); return -1; } - format_bytes(fp, format, indent, "data : ", data, datalen); - if (alen > 0) { + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { error_print(); return -1; } return 1; } +int cms_content_type_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; -/* -EncryptedContentInfo ::= SEQUENCE { - contentType OBJECT IDENTIFIER, - contentEncryptionAlgorithm AlgorithmIdentifier, - encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo1 [1] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo2 [2] IMPLICIT OCTET STRING OPTIONAL, + *oid = 0; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if ((ret = asn1_oid_info_from_der(&info, cms_content_types, cms_content_types_count, &p, &len)) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return ret; + } + *oid = info->oid; + return 1; } -*/ -int cms_enced_content_info_to_der(int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, - int content_type, const uint8_t *enced_content, size_t enced_content_len, +int cms_enced_content_info_to_der( + int content_type, + int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, + const uint8_t *enced_content, size_t enced_content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, uint8_t **out, size_t *outlen) { size_t len = 0; - if (cms_content_type_to_der(content_type, NULL, &len) != 1 || x509_encryption_algor_to_der(enc_algor, enc_iv, enc_iv_len, NULL, &len) != 1 || asn1_implicit_octet_string_to_der(0, enced_content, enced_content_len, NULL, &len) < 0 || asn1_implicit_octet_string_to_der(1, shared_info1, shared_info1_len, NULL, &len) < 0 - || asn1_implicit_octet_string_to_der(2, shared_info2, shared_info2_len, NULL, &len) < 0) { - error_print(); - return -1; - } - if (asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_implicit_octet_string_to_der(2, shared_info2, shared_info2_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 || cms_content_type_to_der(content_type, out, outlen) != 1 || x509_encryption_algor_to_der(enc_algor, enc_iv, enc_iv_len, out, outlen) != 1 || asn1_implicit_octet_string_to_der(0, enced_content, enced_content_len, out, outlen) < 0 @@ -143,655 +167,7 @@ int cms_enced_content_info_to_der(int enc_algor, const uint8_t *enc_iv, size_t e return 1; } -int cms_enced_content_info_from_der(int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - uint32_t nodes[32]; - size_t nodes_count; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (cms_content_type_from_der(content_type, &data, &datalen) != 1 - || x509_encryption_algor_from_der(enc_algor, nodes, &nodes_count, enc_iv, enc_iv_len, &data, &datalen) != 1 - || asn1_implicit_octet_string_from_der(0, enced_content, enced_content_len, &data, &datalen) < 0 - || asn1_implicit_octet_string_from_der(1, shared_info1, shared_info1_len, &data, &datalen) < 0 - || asn1_implicit_octet_string_from_der(2, shared_info2, shared_info2_len, &data, &datalen) < 0 - || asn1_check(datalen == 0) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_enced_content_info_print(FILE *fp, - int content_type, - int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, - const uint8_t *enced_content, size_t enced_content_len, - const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - int format, int indent) -{ - format_print(fp, format, indent, "EncryptedContentInfo:\n"); - indent += 4; - - format_print(fp, format, indent, "contentType: %s\n", cms_content_type_name(content_type)); - format_print(fp, format, indent, "contentEncryptionAlgorithm: %s\n", x509_encryption_algor_name(enc_algor)); - format_bytes(fp, format, indent + 4, "iv: ", enc_iv, enc_iv_len); - format_bytes(fp, format, indent, "encryptedContent: ", enced_content, enced_content_len); - format_bytes(fp, format, indent, "sharedInfo1: ", shared_info1, shared_info1_len); - format_bytes(fp, format, indent, "sharedInfo2: ", shared_info2, shared_info2_len); - return 1; -} - -int cms_enced_content_info_encrypt_to_der(const SM4_KEY *sm4_key, const uint8_t iv[16], - int content_type, const uint8_t *content, size_t content_len, - const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - uint8_t **out, size_t *outlen) -{ - uint8_t enced_content[content_len + 256]; - size_t enced_content_len; - - if (sm4_cbc_padding_encrypt(sm4_key, iv, content, content_len, - enced_content, &enced_content_len) != 1) { - error_print(); - return -1; - } - if (cms_enced_content_info_to_der(OID_sm4_cbc, iv, 16, - content_type, enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_enced_content_info_decrypt_from_der(const SM4_KEY *key, - int *content_type, uint8_t *content, size_t *content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - int enc_algor; - const uint8_t *enc_iv; - size_t enc_iv_len; - const uint8_t *enced_content; - size_t enced_content_len; - - if ((ret = cms_enced_content_info_from_der(content_type, - &enc_algor, &enc_iv, &enc_iv_len, - &enced_content, &enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (sm4_cbc_padding_decrypt(key, enc_iv, enced_content, enced_content_len, - content, content_len) != 1) { - error_print(); - return -1; - } - return 1; -} - -/* -EncryptedData ::= SEQUENCE { - version INTEGER (1), - encryptedContentInfo EncryptedContentInfo ::= SEQUENCE { - contentType OBJECT IDENTIFIER, - contentEncryptionAlgorithm AlgorithmIdentifier, // 包含参数IV - encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo1 [1] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo2 [2] IMPLICIT OCTET STRING OPTIONAL, -} -*/ - -int cms_encrypted_data_to_der(int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, - int content_type, const uint8_t *enced_content, size_t enced_content_len, - const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || cms_enced_content_info_to_der(enc_algor, enc_iv, enc_iv_len, - content_type, enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - NULL, &len) != 1) { - error_print(); - return -1; - } - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || cms_enced_content_info_to_der(enc_algor, enc_iv, enc_iv_len, - content_type, enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_encrypted_data_decrypt_from_der(const SM4_KEY *key, - int *content_type, uint8_t *content, size_t *content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int version; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - else error_print(); - return ret; - } - if (asn1_int_from_der(&version, &data, &datalen) != 1 - || version != CMS_version) { - error_print(); - return -1; - } - - if (cms_enced_content_info_decrypt_from_der(key, - content_type, content, content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - &data, &datalen) != 1 - || datalen) { - error_print(); - return -1; - } - return 1; -} - -int cms_encrypted_data_from_der(int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int version; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_int_from_der(&version, &data, &datalen) != 1 - || cms_enced_content_info_from_der(content_type, - enc_algor, enc_iv, enc_iv_len, - enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - &data, &datalen) != 1 - || asn1_check(datalen == 0) != 1) { - error_print(); - return -1; - } - if (version != CMS_version) { - error_print(); - return -1; - } - return 1; -} - -int cms_encrypted_data_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent) -{ - int version; - int content_type; - int enc_algor; - const uint8_t *enc_iv; - size_t enc_iv_len; - const uint8_t *enced_content; - size_t enced_content_len; - const uint8_t *shared_info1; - size_t shared_info1_len; - const uint8_t *shared_info2; - size_t shared_info2_len; - - if (cms_encrypted_data_from_der( - &content_type, - &enc_algor, &enc_iv, &enc_iv_len, - &enced_content, &enced_content_len, - &shared_info1, &shared_info1_len, - &shared_info2, &shared_info2_len, - &a, &alen) != 1) { - error_print(); - return -1; - } - - format_print(fp, format, indent, "EncryptedData:\n"); - indent += 4; - format_print(fp, format, indent, "Version : %d\n", version); - cms_enced_content_info_print(fp, - content_type, - enc_algor, enc_iv, enc_iv_len, - enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - format, indent); - - if (alen) { - error_print(); - return -1; - } - return 1; -} - -int cms_encrypted_data_encrypt_to_der(const SM4_KEY *sm4_key, const uint8_t iv[16], - int content_type, const uint8_t *content, size_t content_len, - const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || cms_enced_content_info_encrypt_to_der(sm4_key, iv, - content_type, content, content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - NULL, &len) != 1) { - error_print(); - return -1; - } - - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || cms_enced_content_info_encrypt_to_der(sm4_key, iv, - content_type, content, content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - - -/* -KeyAgreementInfo ::= SEQUENCE { - version INTEGER (1), - tempPublicKeyR SM2PublicKey, - userCertificate Certificate, - userID OCTET STRING -} -*/ - -int cms_key_agreement_info_to_der(const SM2_KEY *pub_key, const X509_CERTIFICATE *cert, - const uint8_t *user_id, size_t user_id_len, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || sm2_public_key_info_to_der(pub_key, NULL, &len) != 1 - || x509_certificate_to_der(cert, NULL, &len) != 1 - || asn1_octet_string_to_der(user_id, user_id_len, NULL, &len) != 1) { - error_print(); - return -1; - } - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || sm2_public_key_info_to_der(pub_key, out, outlen) != 1 - || x509_certificate_to_der(cert, out, outlen) != 1 - || asn1_octet_string_to_der(user_id, user_id_len, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_key_agreement_info_from_der(SM2_KEY *pub_key, X509_CERTIFICATE *cert, - const uint8_t **user_id, size_t *user_id_len, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int version; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_int_from_der(&version, &data, &datalen) != 1 - || sm2_public_key_info_from_der(pub_key, &data, &datalen) != 1 - || x509_certificate_from_der(cert, &data, &datalen) != 1 - || asn1_octet_string_from_der(user_id, user_id_len, &data, &datalen) != 1 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_key_agreement_info_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent) -{ - SM2_KEY pub_key; - X509_CERTIFICATE cert; - const uint8_t *user_id; - size_t user_id_len; - - if (cms_key_agreement_info_from_der(&pub_key, &cert, &user_id, &user_id_len, &a, &alen) != 1) { - error_print(); - return -1; - } - format_print(fp, format, indent, "KeyAgreementInfo :\n"); - indent += 4; - format_print(fp, format, indent, "Version : 1\n"); - format_print(fp, format, indent, "tempPublicKeyR "); - sm2_key_print(fp, &pub_key, format, indent + 4); - format_print(fp, format, indent, "userCertificate "); - x509_certificate_print(fp, &cert, format, indent + 4); - format_bytes(fp, format, indent, "userID : ", user_id, user_id_len); - - if (alen) { - error_print(); - return -1; - } - return 1; -} - -/* -IssuerAndSerialNumber ::= SEQUENCE { - isser Name, - serialNumber INTEGER -} -*/ - -int cms_issuer_and_serial_number_from_certificate(const X509_NAME **issuer, - const uint8_t **serial_number, size_t *serial_number_len, - const X509_CERTIFICATE *cert) -{ - const X509_TBS_CERTIFICATE *tbs = &cert->tbs_certificate; - *issuer = &tbs->issuer; - *serial_number = tbs->serial_number; - *serial_number_len = tbs->serial_number_len; - return 1; -} - -int cms_public_key_from_certificate(const SM2_KEY **sm2_key, - const X509_CERTIFICATE *cert) -{ - const X509_TBS_CERTIFICATE *tbs = &cert->tbs_certificate; - *sm2_key = &tbs->subject_public_key_info.sm2_key; - return 1; -} - -int cms_issuer_and_serial_number_to_der(const X509_NAME *issuer, - const uint8_t *serial_number, size_t serial_number_len, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (x509_name_to_der(issuer, NULL, &len) != 1 - || asn1_integer_to_der(serial_number, serial_number_len, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_name_to_der(issuer, out, outlen) != 1 - || asn1_integer_to_der(serial_number, serial_number_len, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_issuer_and_serial_number_from_der(X509_NAME *issuer, - const uint8_t **serial_number, size_t *serial_number_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_name_from_der(issuer, &data, &datalen) != 1 - || asn1_integer_from_der(serial_number, serial_number_len, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int cms_issuer_and_serial_number_print(FILE *fp, - const X509_NAME *issuer, - const uint8_t *serial_number, size_t serial_number_len, - int format, int indent) -{ - format_print(fp, format, indent, "IssuerAndSerialNumber:\n"); - indent += 4; - format_print(fp, format, indent, "issuer:\n"); - x509_name_print(fp, issuer, format, indent + 4); - format_bytes(fp, format, indent, "serialNumber: ", serial_number, serial_number_len); - return 1; -} - -/* -RecipientInfo ::= SEQUENCE { - version INTEGER (1), - issuerAndSerialNumber IssuerAndSerialNumber, - keyEncryptionAlgorithm AlgorithmIdentifier, - encryptedKey OCTET STRING // 包含SM2Ciphertext的DER编码,变长数据 -} -*/ - -int cms_recipient_info_from_x509_certificate( - const SM2_KEY **key, - const X509_NAME **issuer, - const uint8_t **serial_number, size_t *serial_number_len, - const X509_CERTIFICATE *cert) -{ - *issuer = &cert->tbs_certificate.issuer; - *serial_number = &cert->tbs_certificate.serial_number[0]; - *serial_number_len = cert->tbs_certificate.serial_number_len; - *key = &cert->tbs_certificate.subject_public_key_info.sm2_key; - return 1; -} - - -int cms_recipient_info_to_der(const X509_NAME *issuer, - const uint8_t *serial_number, size_t serial_number_len, - const uint8_t *enced_key, size_t enced_key_len, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || cms_issuer_and_serial_number_to_der(issuer, serial_number, serial_number_len, NULL, &len) != 1 - || x509_public_key_encryption_algor_to_der(OID_sm2encrypt, NULL, &len) != 1 - || asn1_octet_string_to_der(enced_key, enced_key_len, NULL, &len) != 1) { - error_print(); - return -1; - } - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || cms_issuer_and_serial_number_to_der(issuer, serial_number, serial_number_len, out, outlen) != 1 - || x509_public_key_encryption_algor_to_der(OID_sm2encrypt, out, outlen) != 1 - || asn1_octet_string_to_der(enced_key, enced_key_len, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_recipient_info_from_der( - int *version, - X509_NAME *issuer, - const uint8_t **serial_number, size_t *serial_number_len, - int *pke_algor, const uint8_t **params, size_t *paramslen, - const uint8_t **enced_key, size_t *enced_key_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - uint32_t pke_algor_nodes[32]; - size_t pke_algor_nodes_count; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_int_from_der(version, &data, &datalen) != 1) { - error_print(); - return -1; - } - if (cms_issuer_and_serial_number_from_der(issuer, serial_number, serial_number_len, &data, &datalen) != 1 - || x509_public_key_encryption_algor_from_der(pke_algor, pke_algor_nodes, &pke_algor_nodes_count, params, paramslen, &data, &datalen) != 1) { - error_print(); - return -1; - } - if (asn1_octet_string_from_der(enced_key, enced_key_len, &data, &datalen) != 1 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - if (*version != CMS_version) { - error_print(); - return -1; - } - - return 1; -} - -int cms_recipient_info_print(FILE *fp, - int version, - const X509_NAME *issuer, const uint8_t *serial_number, size_t serial_number_len, - int pke_algor, const uint8_t *params, size_t paramslen, - const uint8_t *enced_key, size_t enced_key_len, - int format, int indent) -{ - format_print(fp, format, indent, "RecipientInfo:\n"); - indent += 4; - format_print(fp, format, indent, "Version: %d\n", version); - cms_issuer_and_serial_number_print(fp, issuer, serial_number, serial_number_len, format, indent); - format_print(fp, format, indent, "KeyEncryptionAlgorithm: %s\n", x509_public_key_encryption_algor_name(pke_algor)); - /* - if (params && paramslen) { - format_bytes(fp, format, indent + 4, "parameters: ", params, paramslen); - } - */ - format_bytes(fp, format, indent, "EncryptedKey: ", enced_key, enced_key_len); - return 1; -} - - -int cms_recipient_info_encrypt_to_der(const SM2_KEY *sm2_key, - const X509_NAME *issuer, const uint8_t *serial_number, size_t serial_number_len, - const uint8_t *key, size_t keylen, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - uint8_t buf[keylen + 256]; - size_t buflen; - - sm2_encrypt(sm2_key, key, keylen, buf, &buflen); - - cms_recipient_info_to_der(issuer, serial_number, serial_number_len, - buf, buflen, out, outlen); - - return 1; -} - -int cms_recipient_info_decrypt_from_der(const SM2_KEY *sm2_key, - X509_NAME *issuer, const uint8_t **serial_number, size_t *serial_number_len, - uint8_t *key, size_t *keylen, - const uint8_t **in, size_t *inlen) -{ - int ret; - int version; - int pke_algor; - const uint8_t *pke_params; - size_t pke_params_len; - const uint8_t *enced_key; - size_t enced_key_len; - - if ((ret = cms_recipient_info_from_der(&version, - issuer, serial_number, serial_number_len, - &pke_algor, &pke_params, &pke_params_len, - &enced_key, &enced_key_len, - in, inlen)) != 1 - || asn1_check(version == CMS_version) != 1 - || asn1_check(pke_algor == OID_sm2encrypt) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (sm2_decrypt(sm2_key, enced_key, enced_key_len, key, keylen) != 1) { - error_print(); - return -1; - } - - return 1; -} - -/* -EnvelopedData ::= SEQUENCE { - version INTEGER (1), - recipientInfos SET OF RecipientInfo, - encryptedContentInfo EncryptedContentInfo ::= SEQUENCE { - contentType OBJECT IDENTIFIER, - contentEncryptionAlgorithm AlgorithmIdentifier, // 包含IV - encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo1 [1] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo2 [2] IMPLICIT OCTET STRING OPTIONAL, - } -} - - -ContentInfo ::= SEQUENCE { - contentType OBJECT IDENTIFIER, - content [0] EXPLICIT ANY OPTIONAL - -这里到底加密的是什么? - -"content octets of the definite-length BER encoding of the the content field of - ContentInfo value" - -ContentInfo.content 是一个封装在explicit [0]中的一个完整的TLV的值 -要加密的就是这个值(可能是另外一个ContentInfo) -只有当这个ContentInfo类型是data时,只是用来处理数据 - -*/ - -// 这个函数几乎是没有用的,因为我们用一个整体的函数去调用这个功能 -int cms_enveloped_data_to_der(const uint8_t *rcpt_infos, size_t rcpt_infos_len, - int content_type, - int enc_algor, - const uint8_t *enc_iv, size_t enc_iv_len, - const uint8_t *enced_content, size_t enced_content_len, - const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - const uint8_t **out, size_t *outlen) -{ - return -1; -} - -int cms_enveloped_data_from_der(const uint8_t **rcpt_infos, size_t *rcpt_infos_len, +int cms_enced_content_info_from_der( int *content_type, int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, const uint8_t **enced_content, size_t *enced_content_len, @@ -800,1735 +176,148 @@ int cms_enveloped_data_from_der(const uint8_t **rcpt_infos, size_t *rcpt_infos_l const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; - int version; + const uint8_t *d; + size_t dlen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_int_from_der(&version, &data, &datalen) != 1 - || asn1_set_from_der(rcpt_infos, rcpt_infos_len, &data, &datalen) != 1 - || cms_enced_content_info_from_der(content_type, - enc_algor, enc_iv, enc_iv_len, - enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - &data, &datalen) != 1 - || asn1_check(datalen == 0) != 1) { + if (cms_content_type_from_der(content_type, &d, &dlen) != 1 + || x509_encryption_algor_from_der(enc_algor, enc_iv, enc_iv_len, &d, &dlen) != 1 + || asn1_implicit_octet_string_from_der(0, enced_content, enced_content_len, &d, &dlen) < 0 + || asn1_implicit_octet_string_from_der(1, shared_info1, shared_info1_len, &d, &dlen) < 0 + || asn1_implicit_octet_string_from_der(2, shared_info2, shared_info2_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } return 1; } - -// 不做解密,打印加密的RecipientInfo和EncryptedContentInfo -int cms_enveloped_data_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent) +int cms_enced_content_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - const uint8_t *rcpt_infos; - size_t rcpt_infos_len; - int content_type; - int enc_algor; - const uint8_t *enc_iv; - const uint8_t *enced_content; - const uint8_t *shared_info1; - const uint8_t *shared_info2; - size_t enc_iv_len, enced_content_len, shared_info1_len, shared_info2_len; + int ret, val; + const uint8_t *p; + size_t len; - if (cms_enveloped_data_from_der(&rcpt_infos, &rcpt_infos_len, - &content_type, &enc_algor, &enc_iv, &enc_iv_len, - &enced_content, &enced_content_len, - &shared_info1, &shared_info1_len, - &shared_info2, &shared_info2_len, - &a, &alen) != 1) { - error_print(); - return -1; - } + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; - format_print(fp, format, indent, "EnvelopedData:\n"); - indent += 4; - format_print(fp, format, indent, "Version: %d\n", CMS_version); - - - format_print(fp, format, indent, "RecipientInfos:\n"); - while (rcpt_infos_len) { - int version; - X509_NAME issuer; - const uint8_t *serial_number; - size_t serial_number_len; - int pke_algor; - const uint8_t *pke_params; - size_t pke_params_len; - const uint8_t *enced_key; - size_t enced_key_len; - - if (cms_recipient_info_from_der( - &version, - &issuer, &serial_number, &serial_number_len, - &pke_algor, &pke_params, &pke_params_len, - &enced_key, &enced_key_len, - &rcpt_infos, &rcpt_infos_len) != 1) { - error_print(); - return -1; - } - cms_recipient_info_print(fp, - version, - &issuer, serial_number, serial_number_len, - pke_algor, pke_params, pke_params_len, - enced_key, enced_key_len, - format, indent + 4); - } - - cms_enced_content_info_print(fp, - content_type, - enc_algor, enc_iv, enc_iv_len, - enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - format, indent); - - return -1; -} - -// 这个数据长度为什么不一样? -int cms_enveloped_data_encrypt_to_der(const X509_CERTIFICATE *rcpt_certs, size_t rcpt_count, - int content_type, const uint8_t *content, size_t content_len, - const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - SM4_KEY sm4_key; - uint8_t enc_key[16]; - uint8_t enc_iv[16]; - - const SM2_KEY *sm2_key; - const X509_NAME *issuer; - const uint8_t *serial_number; - size_t serial_number_len; - - size_t rcpt_infos_len = 0; - size_t i; - - - rand_bytes(enc_key, 16); - rand_bytes(enc_iv, 16); - - - - - /* - 每次生成的密文长度都是不同的,有SM2Ciphertext决定 - 纯数据为 32 + 32 + 32 + 16 - */ - - for (i = 0; i < rcpt_count; i++) { - cms_recipient_info_from_x509_certificate(&sm2_key, - &issuer, &serial_number, &serial_number_len, - &rcpt_certs[i]); - - rcpt_infos_len = 0; - - // FIXME: 预先估计的长度是不对的,因为每次SM2密文的长度都是不同的! - cms_recipient_info_encrypt_to_der(sm2_key, - issuer, serial_number, serial_number_len, - enc_key, sizeof(enc_key), - NULL, &rcpt_infos_len); - error_print_msg("rcpt_infos_len = %zu\n", rcpt_infos_len); - } - - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || asn1_set_to_der(NULL, rcpt_infos_len, NULL, &len) != 1 - || cms_enced_content_info_encrypt_to_der(&sm4_key, enc_iv, - content_type, content, content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - NULL, &len) != 1) { - error_print(); - return -1; - } - error_print_msg("len = %zu\n", len); - - error_print_msg("outlen = %zu\n", *outlen); - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || asn1_set_header_to_der(rcpt_infos_len, out, outlen) != 1) { - error_print(); - return -1; - } - for (i = 0; i < rcpt_count; i++) { - if (cms_recipient_info_encrypt_to_der(sm2_key, issuer, - serial_number, serial_number_len, - enc_key, sizeof(enc_key), - out, outlen) != 1) { - error_print(); - return -1; - } - } - if (cms_enced_content_info_encrypt_to_der(&sm4_key, enc_iv, - content_type, content, content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - out, outlen) != 1) { - error_print(); - return -1; - } - error_print_msg("outlen = %zu\n", *outlen); + if (cms_content_type_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "contentType: %s\n", cms_content_type_name(val)); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_encryption_algor_print(fp, fmt, ind, "contentEncryptionAlgorithm", p, len); + if ((ret = asn1_implicit_octet_string_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "encryptedContent", d, dlen); + if ((ret = asn1_implicit_octet_string_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "sharedInfo1", d, dlen); + if ((ret = asn1_implicit_octet_string_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "sharedInfo2", d, dlen); + if (asn1_length_is_zero(dlen) != 1) goto err; return 1; -} - -// 这里我们必须在整个RecipientInfos中找到匹配的,然后才能解密 -/* -1. 扫描RecipientInfos,查看是否有和sm2_key, cert匹配的证书 -2. 从找到的RecipientInfo,从加密算法中获取IV,对数据进行私钥解密后得到被加密的对称密钥key -3. 用key, iv对被加密的content进行解密 -*/ -int cms_enveloped_data_decrypt_from_der( - const SM2_KEY *sm2_key, //解密方只有一个私钥,因此不管接收哪来的消息,只能用自己的私钥去尝试解密 - const X509_CERTIFICATE *cert, // 证书用于提供IssuerAndSerialNumber,从RecipientInfos中找到私钥对应的那个 - int *content_type, uint8_t *content, size_t *content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t **in, size_t *inlen) -{ - const uint8_t *rcpt_infos; - size_t rcpt_infos_len; - int enc_algor; - uint32_t enc_algor_nodes[32]; - size_t enc_algor_nodes_count; - const uint8_t *enced_content; - size_t enced_content_len; - uint8_t enc_key[64]; - size_t enc_key_len; - - const uint8_t *enc_iv; - size_t enc_iv_len; - SM4_KEY sm4_key; - - - const X509_NAME *cert_issuer; - const uint8_t *cert_serial; - size_t cert_serial_len; - - if (cms_issuer_and_serial_number_from_certificate(&cert_issuer, - &cert_serial, &cert_serial_len, cert) != 1) { - error_print(); - return -1; - } - - printf("input lenght = %zu\n", *inlen); - - if (cms_enveloped_data_from_der(&rcpt_infos, &rcpt_infos_len, - content_type, &enc_algor, - &enc_iv, &enc_iv_len, - &enced_content, &enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - in, inlen) != 1) { - error_print(); - return -1; - } - if (enc_algor != OID_sm4_cbc) { - error_print(); - return -1; - } - if (!enc_iv || enc_iv_len != 16) { - error_print(); - return -1; - } - - while (rcpt_infos_len) { - int version; - X509_NAME issuer; - const uint8_t *serial_number; - size_t serial_number_len; - int pke_algor; - const uint8_t *pke_params; - size_t pke_params_len; - const uint8_t *enced_key; - size_t enced_key_len; - - if (cms_recipient_info_from_der( - &version, - &issuer, - &serial_number, &serial_number_len, - &pke_algor, &pke_params, &pke_params_len, - &enced_key, &enced_key_len, - &rcpt_infos, &rcpt_infos_len) != 1) { - error_print(); - return -1; - } - // 这里应该检查一下公钥类型到底对不对 - - - - - if (cert_serial_len != serial_number_len - || memcmp(serial_number, cert_serial, cert_serial_len) - || x509_name_equ(cert_issuer, &issuer) != 1) { - continue; - } - - if (sm2_decrypt(sm2_key, enced_key, enced_key_len, enc_key, &enc_key_len) != 1) { - error_print(); - return -1; - } - } - - sm4_set_decrypt_key(&sm4_key, enc_key); - if (sm4_cbc_padding_decrypt( - &sm4_key, enc_iv, - enced_content, enced_content_len, - content, content_len) != 1) { - error_print(); - return -1; - } - - - return 1; -} - - -// 注意,由于SignedData中包含ContentInfo,因此需要提前给出ContentInfo的基本编解码 - -/* -ContentType OIDs - */ - -static const uint32_t OID_cms_data[] = {1,2,156,10197,6,1,4,2,1}; -static const uint32_t OID_cms_signed_data[] = {1,2,156,10197,6,1,4,2,2}; -static const uint32_t OID_cms_enveloped_data[] = {1,2,156,10197,6,1,4,2,3}; -static const uint32_t OID_cms_signed_and_enveloped_data[] = {1,2,156,10197,6,1,4,2,4}; -static const uint32_t OID_cms_encrypted_data[] = {1,2,156,10197,6,1,4,2,5}; -static const uint32_t OID_cms_key_agreement_info[] = {1,2,156,10197,6,1,4,2,6}; - - -const char *cms_content_type_name(int type) -{ - switch (type) { - case CMS_data: return "data"; - case CMS_signed_data: return "signedData"; - case CMS_enveloped_data: return "envelopedData"; - case CMS_signed_and_enveloped_data: return "signedAndEnvelopedData"; - case CMS_encrypted_data: return "encryptedData"; - case CMS_key_agreement_info: return "keyAgreementInfo"; - } - return NULL; -} - -int cms_content_type_to_der(int type, uint8_t **out, size_t *outlen) -{ - uint32_t cms_nodes[9] = {1,2,156,10197,6,1,4,2,0}; - - if (!cms_content_type_name(type)) { - error_print(); - return -1; - } - cms_nodes[8] = type; - if (asn1_object_identifier_to_der(OID_undef, cms_nodes, 9, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int cms_content_type_from_der(int *type, const uint8_t **in, size_t *inlen) -{ - const uint32_t cms_nodes[] = {1,2,156,10197,6,1,4,2,0}; - int ret; - - uint32_t nodes[32]; - size_t nodes_count; - - if (( ret = asn1_object_identifier_from_der(type, nodes, &nodes_count, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - - if (*type == OID_undef) { - if (nodes_count != 9) { - error_print(); - return -1; - } - if (memcmp(nodes, cms_nodes, 8) != 0) { - error_print(); - return -1; - } - if (cms_content_type_name(nodes[8]) == NULL) { - error_print(); - return -1; - } - *type = nodes[8]; - } - return 1; -} - - -/* -ContentInfo ::= SEQUENCE { - contentType OBJECT IDENTIFIER, - content [0] EXPLICIT ANY OPTIONAL -} -*/ - -int cms_content_info_to_der(int content_type, const uint8_t *content, size_t content_len, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (content_type == CMS_data) { - size_t octets_len = 0; - if (asn1_octet_string_to_der(content, content_len, NULL, &octets_len) != 1 - || cms_content_type_to_der(content_type, NULL, &len) != 1 - || asn1_explicit_to_der(0, NULL, octets_len, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || cms_content_type_to_der(content_type, out, outlen) != 1 - || asn1_explicit_header_to_der(0, octets_len, out, outlen) != 1 - || asn1_octet_string_to_der(content, content_len, out, outlen) != 1) { - error_print(); - return -1; - } - } else { - if (cms_content_type_to_der(content_type, NULL, &len) != 1 - || asn1_explicit_to_der(0, content, content_len, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || cms_content_type_to_der(content_type, out, outlen) != 1 - || asn1_explicit_to_der(0, content, content_len, out, outlen) != 1) { - error_print(); - return -1; - } - } - return 1; -} - -int cms_content_info_from_der(int *content_type, const uint8_t **content, size_t *content_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (cms_content_type_from_der(content_type, &data, &datalen) != 1 - || asn1_explicit_from_der(0, content, content_len, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -/* -SignerInfo ::= SEQUENCE { - version INTEGER (1), - issuerAndSerialNumber IssuerAndSerialNumber, - digestAlgorithm AlgorithmIdentifier, - authenticatedAttributes [0] IMPLICIT SET OF Attribute OPTINOAL, - digestEncryptionAlgorithm AlgorithmIdentifier, - encryptedDigest OCTET STRING, // 变长字符串 - unauthenticatedAttributes [1] IMPLICIT SET OF Attribute OPTINOAL, -} -*/ - -int cms_signer_info_to_der( - const X509_NAME *issuer, - const uint8_t *serial_number, size_t serial_number_len, - int digest_algor, - const uint8_t *authed_attrs, size_t authed_attrs_len, - const uint8_t *enced_digest, size_t enced_digest_len, - const uint8_t *unauthed_attrs, size_t unauthed_attrs_len, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || cms_issuer_and_serial_number_to_der(issuer, serial_number, serial_number_len, NULL, &len) != 1 - || x509_digest_algor_to_der(OID_sm3, NULL, &len) != 1 - || asn1_implicit_set_to_der(0, authed_attrs, authed_attrs_len, NULL, &len) < 0 - || x509_signature_algor_to_der(OID_sm2sign_with_sm3, NULL, &len) != 1 - || asn1_octet_string_to_der(enced_digest, enced_digest_len, NULL, &len) != 1 - || asn1_implicit_set_to_der(1, unauthed_attrs, unauthed_attrs_len, NULL, &len) < 0) { - error_print(); - return -1; - } - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || cms_issuer_and_serial_number_to_der(issuer, serial_number, serial_number_len, out, outlen) != 1 - || x509_digest_algor_to_der(OID_sm3, out, outlen) != 1) { - error_print(); - return -1; - } - if (0 - || asn1_implicit_set_to_der(0, authed_attrs, authed_attrs_len, out, outlen) < 0) { - error_print(); - return -1; - } - if (0 - || x509_signature_algor_to_der(OID_sm2sign_with_sm3, out, outlen) != 1) { - error_print(); - return -1; - } - if (0 - || asn1_octet_string_to_der(enced_digest, enced_digest_len, out, outlen) != 1 - || asn1_implicit_set_to_der(1, unauthed_attrs, unauthed_attrs_len, out, outlen) < 0) { - error_print(); - return -1; - } - return 1; -} - -int cms_signer_info_from_der(X509_NAME *issuer, - const uint8_t **serial_number, size_t *serial_number_len, - int *digest_algor, - const uint8_t **authed_attrs, size_t *authed_attrs_len, - int *sign_algor, - const uint8_t **enced_digest, size_t *enced_digest_len, - const uint8_t **unauthed_attrs, size_t *unauthed_attrs_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int version; - uint32_t nodes[32]; - size_t nodes_count; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_int_from_der(&version, &data, &datalen) != 1 - || cms_issuer_and_serial_number_from_der(issuer, serial_number, serial_number_len, &data, &datalen) != 1 - || x509_digest_algor_from_der(digest_algor, nodes, &nodes_count, &data, &datalen) != 1 - || asn1_implicit_set_from_der(0, authed_attrs, authed_attrs_len, &data, &datalen) < 0 - || x509_signature_algor_from_der(sign_algor, nodes, &nodes_count, &data, &datalen) != 1 - || asn1_octet_string_from_der(enced_digest, enced_digest_len, &data, &datalen) != 1 - || asn1_implicit_set_from_der(1, unauthed_attrs, unauthed_attrs_len, &data, &datalen) < 0 - || datalen) { - error_print(); - return -1; - } - return 1; -} - -int cms_signer_info_print(FILE *fp, - int version, - const X509_NAME *issuer, const uint8_t *serial_number, size_t serial_number_len, - int digest_algor, const uint8_t *digest_params, size_t digest_params_len, - const uint8_t *authed_attrs, size_t authed_attrs_len, - int sign_algor, const uint8_t *sign_params, size_t sign_params_len, - const uint8_t *sig, size_t siglen, - const uint8_t *unauthed_attrs, size_t unauthed_attrs_len, - int format, int indent) -{ - format_print(fp, format, indent, "SignerInfo:\n"); - indent += 4; - format_print(fp, format, indent, "Version: %d\n", version); - cms_issuer_and_serial_number_print(fp, issuer, serial_number, serial_number_len, format, indent); - format_print(fp, format, indent, "digestAlgorithm: %s\n", x509_digest_algor_name(digest_algor)); - - if (digest_params && digest_params_len) - format_bytes(fp, format, indent, "Parameters: ", digest_params, digest_params_len); - if (authed_attrs && authed_attrs_len) { - format_bytes(fp, format, indent, "AuthenticatedAttributes: ", authed_attrs, authed_attrs_len); - } - - format_print(fp, format, indent, "digestEncryptionAlgorithm: %s\n", x509_signature_algor_name(sign_algor)); - format_bytes(fp, format, indent, "encryptedDigest: ", sig, siglen); - if (unauthed_attrs && unauthed_attrs_len) { - format_bytes(fp, format, indent, "AuthenticatedAttributes: ", unauthed_attrs, unauthed_attrs_len); - } - return 1; -} - -int cms_signer_info_sign_to_der(const SM2_KEY *sm2_key, const SM3_CTX *sm3_ctx, - const X509_NAME *issuer, const uint8_t *serial_number, size_t serial_number_len, - const uint8_t *authed_attrs, size_t authed_attrs_len, - const uint8_t *unauthed_attrs, size_t unauthed_attrs_len, - uint8_t **out, size_t *outlen) -{ - SM3_CTX ctx; - uint8_t dgst[32]; - uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; - size_t sig_len; - - memcpy(&ctx, sm3_ctx, sizeof(SM3_CTX)); - if (authed_attrs) { - uint8_t header[8]; - uint8_t *p = header; - size_t header_len = 0; - asn1_set_header_to_der(authed_attrs_len, &p, &header_len); - sm3_update(&ctx, header, header_len); - sm3_update(&ctx, authed_attrs, authed_attrs_len); - } - sm3_finish(&ctx, dgst); - sm2_sign(sm2_key, dgst, sig, &sig_len); - - if (cms_signer_info_to_der(issuer, serial_number, serial_number_len, - OID_sm3, authed_attrs, authed_attrs_len, sig, sig_len, - unauthed_attrs, unauthed_attrs_len, - out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -/* -1. 解析SignerInfo获得IssuerAndSerialNumber -2. 查找SignedData中的Certificates获得签名公钥 -3. 计算ContentInfo获得杂凑状态 -4. 加入AuthedAttributes得到杂凑值 -5. 验证签名 -*/ -int cms_signer_info_verify( - const SM2_KEY *sm2_key, const SM3_CTX *sm3_ctx, - const uint8_t *authed_attrs, size_t authed_attrs_len, - const uint8_t *sig, size_t siglen) -{ - int ret; - SM3_CTX ctx; - uint8_t dgst[32]; - - memcpy(&ctx, sm3_ctx, sizeof(SM3_CTX)); - if (*authed_attrs) { - uint8_t header[8]; - uint8_t *p = header; - size_t header_len = 0; - asn1_set_header_to_der(authed_attrs_len, &p, &header_len); - sm3_update(&ctx, header, header_len); - sm3_update(&ctx, authed_attrs, authed_attrs_len); - } - sm3_finish(&ctx, dgst); - - if ((ret = sm2_verify(sm2_key, dgst, sig, siglen)) != 1) { - error_print(); - return -1; - } - - return ret; -} - -static int x509_digest_algors_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent) -{ - int dgst_algor; - uint32_t dgst_algor_nodes[32]; - size_t dgst_algor_nodes_count; - - format_print(fp, format, indent, "DigestAlgorithms:\n"); - - while (len) { - if (x509_digest_algor_from_der(&dgst_algor, - dgst_algor_nodes, &dgst_algor_nodes_count, - &p, &len) != 1) { - error_print(); - return -1; - } - format_print(fp, format, indent + 4, "%s\n", x509_digest_algor_name(dgst_algor)); - } - return 1; -} - - -static int x509_certificates_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent) -{ - X509_CERTIFICATE cert; - - format_print(fp, format, indent, "Certificates:\n"); - indent += 4; - - while (len) { - if (x509_certificate_from_der(&cert, &p, &len) != 1) { - error_print(); - return -1; - } - x509_certificate_print(fp, &cert, format, indent); - } - return 1; -} - -static int x509_crls_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent) -{ - /* - X509_CRL crl; - while (len) { - if (x509_crl_from_der(&crl, &p, &len) != 1) { - error_print(); - return -1; - } - x509_crl_print(fp, &crl, format, indent); - } - */ - return 1; -} - -static int cms_recipient_infos_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent) -{ - format_print(fp, format, indent, "RecipientInfos:\n"); - while (len) { - int version; - X509_NAME issuer; - const uint8_t *serial_number; - size_t serial_number_len; - int pke_algor; - const uint8_t *pke_params; - size_t pke_params_len; - const uint8_t *enced_key; - size_t enced_key_len; - - if (cms_recipient_info_from_der( - &version, - &issuer, &serial_number, &serial_number_len, - &pke_algor, &pke_params, &pke_params_len, - &enced_key, &enced_key_len, - &p, &len) != 1) { - error_print(); - return -1; - } - - cms_recipient_info_print(fp, - version, - &issuer, serial_number, serial_number_len, - pke_algor, pke_params, pke_params_len, - enced_key, enced_key_len, - format, indent + 4); - } - - return 1; -} - - -static int cms_signer_infos_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent) -{ - format_print(fp, format, indent, "SignerInfos:\n"); - indent += 4; - - while (len) { - int version; - X509_NAME issuer; - const uint8_t *serial_number; - size_t serial_number_len; - int digest_algor; - const uint8_t *digest_params; - size_t digest_params_len; - const uint8_t *authed_attrs; size_t authed_attrs_len; - int sign_algor; - const uint8_t *sign_params; - size_t sign_params_len; - const uint8_t *sig; - size_t siglen; - const uint8_t *unauthed_attrs; size_t unauthed_attrs_len; - - - cms_signer_info_from_der( - &issuer, - &serial_number, &serial_number_len, - &digest_algor, - &authed_attrs, &authed_attrs_len, - &sign_algor, - &sig, &siglen, - &unauthed_attrs, &unauthed_attrs_len, - &p, &len); - - cms_signer_info_print(fp, - version, - &issuer, - serial_number, serial_number_len, - digest_algor, digest_params, digest_params_len, - authed_attrs, authed_attrs_len, - sign_algor, sign_params, sign_params_len, - sig, siglen, - unauthed_attrs, unauthed_attrs_len, - format, indent); - } - - return 1; -} - -// 这个函数有用吗? -int cms_signed_data_to_der( - const int *digest_algors, const size_t digest_algors_count, - const int content_type, const uint8_t *content, const size_t content_len, - const X509_CERTIFICATE *certs, size_t certs_count, - const uint8_t **crls, const size_t *crls_lens, const size_t crls_count, - const uint8_t **signer_infos, size_t *signer_infos_lens, size_t signer_infos_count,// 这个类型有点问题,意味着签名方必须把所有SignerInfo处理好才行 - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - size_t digest_algors_len = 0; - size_t certs_len = 0; - size_t crls_len = 0; - size_t signer_infos_len = 0; - int i; - - for (i = 0; i < digest_algors_count; i++) { - x509_digest_algor_to_der(digest_algors[i], NULL, &digest_algors_len); - } - for (i = 0; i < certs_count; i++) { - x509_certificate_to_der(&certs[i], NULL, &certs_len); - } - for (i = 0; i < crls_count; i++) - crls_len += crls_lens[i]; - for (i = 0; i < signer_infos_count; i++) - signer_infos_len += signer_infos_lens[i]; - - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || asn1_set_to_der(NULL, digest_algors_len, NULL, &len) != 1 - || cms_content_info_to_der(content_type, content, content_len, NULL, &len) != 1 - || asn1_implicit_set_to_der(0, NULL, certs_len, NULL, &len) < 0 - || asn1_implicit_set_to_der(1, NULL, crls_len, NULL, &len) < 0 - || asn1_set_to_der(NULL, signer_infos_len, NULL, &len) != 1) { - error_print(); - return -1; - } - - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || asn1_set_header_to_der(digest_algors_len, out, outlen) != 1) { - error_print(); - return -1; - } - for (i = 0; i < digest_algors_count; i++) { - if (x509_digest_algor_to_der(digest_algors[i], out, outlen) != 1) { - error_print(); - return -1; - } - } - if (cms_content_info_to_der(content_type, content, content_len, out, outlen) != 1) { - error_print(); - return -1; - } - if (certs) { - if (asn1_implicit_set_header_to_der(0, certs_len, out, outlen) != 1) { - error_print(); - return -1; - } - for (i = 0; i < certs_count; i++) { - } - } - if (crls) { - for (i = 0; i < crls_count; i++) { - } - } - - - if (asn1_set_header_to_der(signer_infos_len, out, outlen) != 1) { - } - for (i = 0; i < signer_infos_count; i++) { - asn1_data_to_der(signer_infos[i], signer_infos_lens[i], out, outlen); - } - - return -1; -} - -int cms_signed_data_from_der( - const uint8_t **digest_algors, size_t *digest_algors_len, - int *content_type, const uint8_t **content, size_t *content_len, - const uint8_t **certs, size_t *certs_len, - const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int version; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - - if (asn1_int_from_der(&version, &data, &datalen) != 1 - || asn1_set_from_der(digest_algors, digest_algors_len, &data, &datalen) != 1 - || cms_content_info_from_der(content_type, content, content_len, &data, &datalen) != 1) { - error_print(); - return -1; - } - - if ((ret = asn1_implicit_set_from_der(0, certs, certs_len, &data, &datalen)) < 0) { - error_print(); - return -1; - } - if (ret == 0) { - // printf("no certs\n"); - } - - if ((ret = asn1_implicit_set_from_der(1, crls, crls_len, &data, &datalen)) < 0) { - error_print(); - return -1; - } - - - if (asn1_set_from_der(signer_infos, signer_infos_len, &data, &datalen) != 1) { - error_print(); - return -1; - } - - if (asn1_length_is_zero(datalen) != 1) { - error_print(); - //return -1; - } - if (version != CMS_version) { - error_print(); - //return -1; - } - return 1; -} - -static int content_info_print(FILE *fp, - int content_type, const uint8_t *content, size_t content_len, - int format, int indent) -{ - - format_print(fp, format, indent, "ContentInfo:\n"); - indent += 4; - format_print(fp, format, indent, "Type : %s\n", cms_content_type_name(content_type)); - switch (content_type) { - case CMS_data: return cms_data_print(fp, content, content_len, format, indent); - case CMS_signed_data: return cms_signed_data_print(fp, content, content_len, format, indent); - case CMS_enveloped_data: break; - case CMS_signed_and_enveloped_data: break; - case CMS_encrypted_data: return cms_encrypted_data_print(fp, content, content_len, format, indent); - case CMS_key_agreement_info: return cms_key_agreement_info_print(fp, content, content_len, format, indent); - } +err: error_print(); return -1; } -// 这几个类型的打印有相当多的重复部分 -int cms_signed_data_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent) -{ - int version = 1; - const uint8_t *dgst_algors; - int content_type; - const uint8_t *content; - const uint8_t *certs; - const uint8_t *crls; - const uint8_t *signer_infos; - size_t dgst_algors_len, content_len, certs_len, crls_len, signer_infos_len; - - if (cms_signed_data_from_der( - &dgst_algors, &dgst_algors_len, - &content_type, &content, &content_len, - &certs, &certs_len, - &crls, &crls_len, - &signer_infos, &signer_infos_len, - &a, &alen) != 1) { - error_print(); - // return -1; - } - - format_print(fp, format, indent, "SignedData:\n"); - indent += 4; - format_print(fp, format, indent, "Version : %d\n", version); - x509_digest_algors_print(fp, dgst_algors, dgst_algors_len, format, indent); - content_info_print(fp, content_type, content, content_len, format, indent); - - x509_certificates_print(fp, certs, certs_len, format, indent); - - - x509_crls_print(fp, crls, crls_len, format, indent); - cms_signer_infos_print(fp, signer_infos, signer_infos_len, format, indent); - return 1; -} - -/* -SignedData ::= SEQUENCE { - version INTEGER (1), - digestAlgorithms SET OF AlgorithmIdentifier, - contentInfo ContentInfo, - certificates [0] IMPLICIT SET OF Certificate OPTIONAL, - crls [1] IMPLICIT SET OF CertificateRevocationList OPTIONAL, - signerInfos SET OF SignerInfo -} - -应该把CRL模块完成后再补全? -还是暂时不支持CRL? -*/ - -int cms_signed_data_sign_to_der( - const SM2_KEY *sign_keys, const X509_CERTIFICATE *sign_certs, size_t sign_count, - int content_type, const uint8_t *content, size_t content_len, - const uint8_t *crls, size_t crls_len, - uint8_t **out, size_t *outlen) -{ - uint8_t *p; - size_t len = 0; - uint8_t digest_algors[16]; // 这里我们只有一个哈希函数 - size_t digest_algors_len = 0; - size_t certs_len = 0; - size_t signer_infos_len = 0; - uint8_t sigs[sign_count][SM2_MAX_SIGNATURE_SIZE]; - size_t siglens[sign_count]; - int i; - - // digestAlgorithms - p = digest_algors; - x509_digest_algor_to_der(OID_sm3, &p, &digest_algors_len); - - // certificates - for (i = 0; i < sign_count; i++) { - if (x509_certificate_to_der(&sign_certs[i], NULL, &certs_len) != 1) { - error_print(); - return -1; - } - } - - // signerInfos - for (i = 0; i < sign_count; i++) { - const X509_CERTIFICATE *cert = &sign_certs[i]; - const X509_NAME *issuer = &cert->tbs_certificate.issuer; - const uint8_t *serial_number = cert->tbs_certificate.serial_number; - size_t serial_number_len = cert->tbs_certificate.serial_number_len; - - SM2_SIGN_CTX sign_ctx; - sm2_sign_init(&sign_ctx, &sign_keys[i], SM2_DEFAULT_ID); - sm2_sign_update(&sign_ctx, content, content_len); // 这里我们签名的都是content - sm2_sign_finish(&sign_ctx, sigs[i], &siglens[i]); - - if (cms_signer_info_to_der(issuer, serial_number, serial_number_len, - OID_sm3, NULL, 0, sigs[i], siglens[i], NULL, 0, - NULL, &signer_infos_len) != 1) { - error_print(); - return -1; - } - } - - - len = 0; - if (asn1_int_to_der(CMS_version, NULL, &len) != 1 - || asn1_set_to_der(digest_algors, digest_algors_len, NULL, &len) != 1 - || cms_content_info_to_der(content_type, content, content_len, NULL, &len) != 1 - || asn1_implicit_set_to_der(0, NULL, certs_len, NULL, &len) < 0 - || asn1_implicit_set_to_der(1, NULL, crls_len, NULL, &len) < 0 - || asn1_set_to_der(NULL, signer_infos_len, NULL, &len) != 1) { - error_print(); - return -1; - } - - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(CMS_version, out, outlen) != 1 - || asn1_set_to_der(digest_algors, digest_algors_len, out, outlen) != 1 - || cms_content_info_to_der(content_type, content, content_len, out, outlen) != 1 - || asn1_implicit_set_header_to_der(0, certs_len, out, outlen) != 1) { - error_print(); - return -1; - } - - for (i = 0; i < sign_count; i++) { - if (x509_certificate_to_der(&sign_certs[i], out, outlen) != 1) { - error_print(); - return -1; - } - } - if (crls) { - if (asn1_implicit_set_to_der(1, crls, crls_len, out, outlen) != 1) { - error_print(); - return -1; - } - } - asn1_set_header_to_der(signer_infos_len, out, outlen); - for (i = 0; i < sign_count; i++) { - const X509_CERTIFICATE *cert = &sign_certs[i]; - const X509_NAME *issuer = &cert->tbs_certificate.issuer; - const uint8_t *serial_number = cert->tbs_certificate.serial_number; - size_t serial_number_len = cert->tbs_certificate.serial_number_len; - - if (cms_signer_info_to_der(issuer, serial_number, serial_number_len, - OID_sm3, NULL, 0, sigs[i], siglens[i], NULL, 0, out, outlen) != 1) { - error_print(); - return -1; - } - } - - return 1; -} - -// 这里的主要矛盾是验证过程没有必要返回那么多数据!只能造成工作量过大, -// 如果调用方想要获得相应的数据,可以自己来解析。 - - -int cms_signed_data_verify( - int content_type, const uint8_t *content, size_t content_len, // 被签名的到底是什么数据? - const uint8_t *certs, size_t certs_len, - const uint8_t *signer_infos, size_t signer_infos_len) -{ - - assert(content); - assert(certs); - assert(signer_infos); - - - while (signer_infos_len) { - - X509_NAME issuer; - const uint8_t *serial_number; - size_t serial_number_len; - const uint8_t *authed_attrs; - size_t authed_attrs_len; - const uint8_t *unauthed_attrs; - size_t unauthed_attrs_len; - const uint8_t *sig; - size_t siglen; - int dgst_algor, sign_algor; - - cms_signer_info_from_der(&issuer, - &serial_number, &serial_number_len, - &dgst_algor, - &authed_attrs, &authed_attrs_len, - &sign_algor, - &sig, &siglen, - &unauthed_attrs, &unauthed_attrs_len, - &signer_infos, &signer_infos_len); - - - // 找到对应的SM2_KEY ,并且验证签名 - X509_CERTIFICATE cert; - - // 主要的挑战就是找到对应的张数 - find_cert(&cert, certs, certs_len, &issuer, serial_number, serial_number_len); - - const SM2_KEY *sign_key = &cert.tbs_certificate.subject_public_key_info.sm2_key; - - SM2_SIGN_CTX ctx; - - sm2_verify_init(&ctx, sign_key, SM2_DEFAULT_ID); - sm2_verify_update(&ctx, content, content_len); - - - if (authed_attrs) { - uint8_t header[8]; - uint8_t *p = header; - size_t header_len = 0; - - asn1_set_header_to_der(*authed_attrs, &p, &header_len); - sm2_verify_update(&ctx, header, header_len); - sm2_verify_update(&ctx, authed_attrs, authed_attrs_len); - } - - int ret; - ret = sm2_verify_finish(&ctx, sig, siglen); - - if (ret != 1) { - error_print_msg("sm2_verify_finish return %d\n", ret); - return -1; - } - - } - - return 1; -} - - -// 为什么不用这个函数 -int cms_signed_data_verify_from_der( - const uint8_t **digest_algors, size_t *digest_algors_len, - int *content_type, const uint8_t **content, size_t *content_len, - const uint8_t **certs, size_t *certs_len, - const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - - if ((ret = cms_signed_data_from_der( - digest_algors, digest_algors_len, - content_type, content, content_len, - certs, certs_len, - crls, crls_len, - signer_infos, signer_infos_len, - in, inlen)) != 1) { - - if (ret < 0) error_print(); - return ret; - } - - if (cms_signed_data_verify( - *content_type, *content, *content_len, - *certs, *certs_len, - *signer_infos, *signer_infos_len) != 1) { - error_print(); - return -1; - } - - return 1; -} - - -/* -SignedAndEnvelopedData ::= SEQUENCE { - version INTEGER (1), - recipientInfos SET OF RecipientInfo, - digestAlgorithms SET OF AlgorithmIdentifier, - encryptedContentInfo EncryptedContentInfo ::= SEQUENCE { - contentType OBJECT IDENTIFIER, - contentEncryptionAlgorithm AlgorithmIdentifier, // 包含IV - encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo1 [1] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo2 [2] IMPLICIT OCTET STRING OPTIONAL, - certificates [0] IMPLICIT SET OF Certificate OPTIONAL, - crls [1] IMPLICIT SET OF CertificateRevocationList OPTIONAL, - signerInfos SET OF SignerInfo -} - -1. 生成随机的content-encryption key (CEK) -2. 用每个接收者的公钥加密CEK -3. 并形成RecipientInfo -4. 根据签名者的算法生成content的哈希值,目前只支持SM3算法,注意涉及Z值 -5. 用签名者的私钥对content的哈希值及authed_attrs进行签名,生成签名值,并且用CEK对签名值加密(可能需要填充) -6. 构造SignerInfos -7. 用CEK对ContentInfo.content中EXPLICIT [0]内部的ContentInfo的DER进行加密 -8. 组成一个SignedAndEnvelopedData - -注意: - -- 这是一个先签名再加密的过程 -- 每个签名值都被对称加密密钥独立加密了 - -*/ - -int cms_signed_and_enveloped_data_to_der( - int version, - const uint8_t *rcpt_infos, size_t rcpt_infos_len, - const int *digest_algors, size_t digest_algors_count, +int cms_enced_content_info_encrypt_to_der( int content_type, - int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, - const uint8_t *enced_content, size_t enced_content_len, - const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - const X509_CERTIFICATE *certs, size_t certs_count, - const uint8_t *crls, size_t crls_count, - const uint8_t signer_infos, size_t signer_infos_len) -{ - - - return -1; -} - -int cms_signed_and_enveloped_data_from_der( - int *version, - const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - const uint8_t **dgst_algors, size_t *dgst_algors_len, - int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t **certs, size_t *certs_len, - const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - - if (asn1_int_from_der(version, &data, &datalen) != 1 - || asn1_set_from_der(rcpt_infos, rcpt_infos_len, &data, &datalen) != 1 - || asn1_set_from_der(dgst_algors, dgst_algors_len, &data, &datalen) != 1 - || cms_enced_content_info_from_der(content_type, - enc_algor, enc_iv, enc_iv_len, - enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - &data, &datalen) != 1 - || asn1_implicit_set_from_der(0, certs, certs_len, &data, &datalen) < 0 - || asn1_implicit_set_from_der(1, crls, crls_len, &data, &datalen) < 0 - || asn1_set_from_der(signer_infos, signer_infos_len, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - - return 1; -} - -int cms_signed_and_enveloped_data_print(FILE *fp, const uint8_t *a, size_t alen, - int format, int indent) -{ - int version; - const uint8_t *rcpt_infos; - const uint8_t *dgst_algors; - const uint8_t *certs; - const uint8_t *crls; - const uint8_t *signer_infos; - size_t rcpt_infos_len, dgst_algors_len, certs_len, crls_len, signer_infos_len; - int content_type; - int enc_algor; - const uint8_t *enc_iv; - const uint8_t *enced_content; - const uint8_t *shared_info1; - const uint8_t *shared_info2; - size_t enc_iv_len, enced_content_len, shared_info1_len, shared_info2_len; - - cms_signed_and_enveloped_data_from_der( - &version, - &rcpt_infos, &rcpt_infos_len, - &dgst_algors, &dgst_algors_len, - &content_type, - &enc_algor, &enc_iv, &enc_iv_len, - &enced_content, &enced_content_len, - &shared_info1, &shared_info1_len, - &shared_info2, &shared_info2_len, - &certs, &certs_len, - &crls, &crls_len, - &signer_infos, &signer_infos_len, - &a, &alen); - - - format_print(fp, format, indent, "SignedAndEnvelopedData:\n"); - indent += 4; - - format_print(fp, format, indent, "Version: %d\n", version); - cms_recipient_infos_print(fp, rcpt_infos, rcpt_infos_len, format, indent); - x509_digest_algors_print(fp, dgst_algors, dgst_algors_len, format, indent); - cms_enced_content_info_print(fp, - content_type, - enc_algor, enc_iv, enc_iv_len, - enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - format, indent); - x509_certificates_print(fp, certs, certs_len, format, indent); - x509_crls_print(fp, crls, crls_len, format, indent); - cms_signer_infos_print(fp, signer_infos, signer_infos_len, format, indent); - - return 1; -} - -/* -SignedAndEnvelopedData ::= SEQUENCE { - version INTEGER (1), - recipientInfos SET OF RecipientInfo, - digestAlgorithms SET OF AlgorithmIdentifier, - encryptedContentInfo EncryptedContentInfo ::= SEQUENCE { - contentType OBJECT IDENTIFIER, - contentEncryptionAlgorithm AlgorithmIdentifier, // 包含IV - encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo1 [1] IMPLICIT OCTET STRING OPTIONAL, - sharedInfo2 [2] IMPLICIT OCTET STRING OPTIONAL, - certificates [0] IMPLICIT SET OF Certificate OPTIONAL, - crls [1] IMPLICIT SET OF CertificateRevocationList OPTIONAL, - signerInfos SET OF SignerInfo -} - - -1. 生成随机的content-encryption key (CEK) -2. 用每个接收者的公钥加密CEK -3. 并形成RecipientInfo -4. 根据签名者的算法生成content的哈希值,目前只支持SM3算法,注意涉及Z值 -5. 用签名者的私钥对content的哈希值及authed_attrs进行签名,生成签名值,并且用CEK对签名值加密(可能需要填充) -6. 构造SignerInfos -7. 用CEK对ContentInfo.content中EXPLICIT [0]内部的ContentInfo的DER进行加密 - -*/ - -// 这个接口是有问题的,显然签名方的证书和密钥没有给出了! -int cms_signed_and_enveloped_data_sign_encrypt_to_der( - const SM2_KEY *sign_keys, const X509_CERTIFICATE *sign_certs, size_t sign_count, - const uint8_t *sign_crls, const size_t sign_crls_len, - const X509_CERTIFICATE *rcpt_certs, size_t rcpt_count, - int content_type, const uint8_t *content, size_t content_len, + int enc_algor, const uint8_t *iv, size_t ivlen, + const uint8_t *content, size_t content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, - + const uint8_t *key, size_t keylen, uint8_t **out, size_t *outlen) { - - return 1; -} - -/* -我们需要保证提供的私钥和证书可以和某个rcpt_infos匹配 -还有一个问题是,在验签之后,我们需要返回所有的证书吗?不需要的,只要可以解析就可以了 -函数保证signer_infos -*/ -int cms_signed_and_enveloped_data_decrypt_verify_from_der( - const SM2_KEY *dec_key, const X509_CERTIFICATE *dec_cert, - const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - const uint8_t **dgst_algors, size_t *dgst_algors_len, - int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t **certs, size_t *certs_len, - const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len) -{ - - /* - signer_info 中的签名是针对未加密的content的 - 因此我们需要首先解析数据结构 - 找到一个和证书、私钥匹配的recipient_info - 解密得到数据加密密钥,并解密enced_content - 然后验证所有的signer_infos - - 这意味着这个函数应该可以和signed_data, enveloped_data共享某些函数 - */ - - - - - - - - - - - - return -1; -} - -int cms_content_info_print(FILE *fp, const uint8_t *a, size_t alen, int format, int indent) -{ - int content_type; - const uint8_t *content; - size_t content_len; - - if (cms_content_info_from_der(&content_type, &content, &content_len, &a, &alen) != 1) { - error_print(); - return -1; - } - if (content_info_print(fp, content_type, content, content_len, format, indent) != 1) { - error_print(); - return -1; - } - if (alen) { - error_print_msg("left length = %zu\n", alen); - format_bytes(stderr, 0, 0, "left ", a, alen); - return -1; - } - - return 1; -} - - - - -// 下面的函数生成的都是ContentInfo -// 因此不简单是之前_to_der的封装,而是要组装成 - - -// EncryptedData -int cms_encrypt(const uint8_t key[16], const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen) -{ - size_t len = 0; - size_t content_len = 0; + int ret; SM4_KEY sm4_key; - uint8_t iv[16]; + uint8_t enced_content[32 + content_len]; + size_t enced_content_len; + + if (enc_algor != OID_sm4_cbc || keylen != 16 || ivlen != 16) { + error_print(); + return -1; + } sm4_set_encrypt_key(&sm4_key, key); - rand_bytes(iv, sizeof(iv)); - - if (cms_encrypted_data_encrypt_to_der(&sm4_key, iv, - CMS_data, in, inlen, NULL, 0, NULL, 0, - NULL, &content_len) != 1) { + if (sm4_cbc_padding_encrypt(&sm4_key, iv, content, content_len, + enced_content, &enced_content_len) != 1) { + memset(&sm4_key, 0, sizeof(SM4_KEY)); error_print(); return -1; } + memset(&sm4_key, 0, sizeof(SM4_KEY)); - if (cms_content_type_to_der(CMS_encrypted_data, NULL, &len) != 1 - || asn1_explicit_to_der(0, NULL, content_len, NULL, &len) != 1) { - error_print(); - return -1; + if ((ret = cms_enced_content_info_to_der(content_type, + enc_algor, iv, ivlen, enced_content, enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; } - - - *outlen = 0; - if (asn1_sequence_header_to_der(len, &out, outlen) != 1 - || cms_content_type_to_der(CMS_encrypted_data, &out, outlen) != 1 - || asn1_explicit_header_to_der(0, content_len, &out, outlen) != 1) { - } - - if (cms_encrypted_data_encrypt_to_der(&sm4_key, iv, CMS_data, in, inlen, - NULL, 0, NULL, 0, &out, outlen) != 1) { - error_print(); - return -1; - } - return 1; } -/* -一般来说,EncryptedData.EncryptedContent.contentType应该是CMS_data -但是也不排除是其他的类型,因此我们需要将这个类型反馈给调用方 -如果是其他类型,那么调用方可以进一步处理 -*/ -int cms_decrypt(const uint8_t key[16], const uint8_t *in, size_t inlen, - int *content_type, uint8_t *out, size_t *outlen) +int cms_enced_content_info_decrypt_from_der( + int *content_type, + int *enc_algor, const uint8_t **iv, size_t *ivlen, + uint8_t *content, size_t *content_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t *key, size_t keylen, + const uint8_t **in, size_t *inlen) { - int cms_type; + int ret; + SM4_KEY sm4_key; const uint8_t *enced_content; size_t enced_content_len; - SM4_KEY sm4_key; - const uint8_t *shared_info1; - const uint8_t *shared_info2; - size_t shared_info1_len, shared_info2_len; - - // decode ContentInfo - if (cms_content_info_from_der(&cms_type, &enced_content, &enced_content_len, - &in, &inlen) != 1) { - error_print(); - return -1; - } - if (cms_type != CMS_encrypted_data) { - error_print(); - return -1; - } - if (inlen) { - error_print(); - return -1; - } - - // decode EncryptedContentInfo - - sm4_set_decrypt_key(&sm4_key, key); - if (cms_encrypted_data_decrypt_from_der(&sm4_key, - content_type, out, outlen, - &shared_info1, &shared_info1_len, - &shared_info2, &shared_info2_len, - &enced_content, &enced_content_len) != 1) { - error_print(); - return -1; - } - if (enced_content_len) { - error_print(); - return 0; - } - - if (shared_info1) { - format_bytes(stderr, 0, 0, "SharedInfo1: ", shared_info1, shared_info1_len); - } - if (shared_info2) { - format_bytes(stderr, 0, 0, "SharedInfo1: ", shared_info2, shared_info2_len); - } - - - return 1; -} - - -// EnvelopedData,其实这个接口可能不是特别好用 -/* - 首先必须考虑到底解密方的证书到底是怎么获得的?如果是多个证书,是从PEM文件中还是从什么方式获得的? - -一般来说,我们在用cms命令行加密的时候,命令的输入应该是多个独立的证书文件。 -那么对我们来说,我们还是直接将证书 - -我觉得还是提供多个独立的证书比较符合实际的需求 - -*/ -int cms_seal(const X509_CERTIFICATE *rcpt_certs, size_t rcpt_count, - const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen) -{ - *outlen = 0; - if (cms_enveloped_data_encrypt_to_der( - rcpt_certs, rcpt_count, - CMS_data, in, inlen, - NULL, 0, NULL, 0, - &out, outlen) != 1) { - error_print(); - return -1; - } - - return 1; -} - -int cms_open(const SM2_KEY *sm2_key, const X509_CERTIFICATE *cert, - const uint8_t *in, size_t inlen, - int *content_type, uint8_t *out, size_t *outlen) -{ - const uint8_t *shared_info1; - const uint8_t *shared_info2; - size_t shared_info1_len, shared_info2_len; - - if (cms_enveloped_data_decrypt_from_der( - sm2_key, cert, - content_type, out, outlen, - &shared_info1, &shared_info1_len, - &shared_info2, &shared_info2_len, - &in, &inlen) != 1) { - error_print(); - return -1; - } - - if (inlen) { - error_print(); - return -1; - } - - return 1; -} - -/* -SM2签名值由于INTEGER编码的问题可能导致编码长度不固定 -因此通常情况下无法预知SignerInfo, SignedData的准确编码长度 -这个问题可以通过对SM2签名模块进行修改来保证签名长度固定 -即使如此,还需要在这个模块中检查signed_data_to_der两次输出长度是相同的 -*/ -int cms_sign(const SM2_KEY *sign_keys, const X509_CERTIFICATE *sign_certs, size_t sign_count, - const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) -{ - size_t len = 0; - size_t signed_data_len = 0; - uint8_t *crls = NULL; - size_t crls_len = 0; - - size_t len2 = 0; - - if (cms_signed_data_sign_to_der(sign_keys, sign_certs, sign_count, - CMS_data, in, inlen, crls, crls_len, - NULL, &signed_data_len) != 1) { - error_print(); - return -1; - } - if (cms_content_type_to_der(CMS_signed_data, NULL, &len) != 1 - || asn1_explicit_to_der(0, NULL, signed_data_len, NULL, &len) != 1) { - error_print(); - return -1; - } - - *outlen = 0; - if (asn1_sequence_header_to_der(len, &out, outlen) != 1 - || cms_content_type_to_der(CMS_signed_data, &out, outlen) != 1 - || asn1_explicit_header_to_der(0, signed_data_len, &out, outlen) != 1 - || cms_signed_data_sign_to_der(sign_keys, sign_certs, sign_count, - CMS_data, in, inlen, crls, crls_len, - &out, &len2) != 1) { - error_print(); - return -1; - } - - if (len2 != signed_data_len) { - error_print(); - - error_print_msg("len = %zu\n", len2); - error_print_msg("signed_data_len = %zu\n", signed_data_len); - - return -1; - } - - *outlen += signed_data_len; - return 1; -} - -// SignedData 中包含被被签名数据、签名值、签名方的证书,因此是完整的 -// 并且包含多个签名值 -// 签名验证成功或者失败,应该返回一些信息,比如到底有哪些签名方?或者验签失败是哪个失败了? -// 我们不太容易反馈复杂的错误信息 -// 如果是命令行,我们需要输出数据和签名者的信息 -// 签名者除了打印名字,还应该把签名者的证书输出出来 -// 这里面主要的问题是,是否需要提供部分数据呢?我看是不需要的,因此必须能够获得被签名的数据和签名者的证书 -// 因此还是调用from_der比较好吧 -// 我们应该把一些相关信息直接打印出来! - -int cms_verify(int *content_type, const uint8_t **content, size_t *content_len, - const uint8_t **certs, size_t *certs_len, - const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - const uint8_t *in, size_t inlen) -{ - int cms_type; - const uint8_t *data; - size_t datalen; - - const uint8_t *dgst_algors; - size_t dgst_algors_len; - - - if (cms_content_info_from_der(&cms_type, &data, &datalen, &in, &inlen) != 1) { - error_print(); - return -1; - } - if (cms_type != CMS_signed_data) { - error_print(); - return -1; - } - - if (cms_signed_data_verify_from_der( - &dgst_algors, &dgst_algors_len, - content_type, content, content_len, - certs, certs_len, - crls, crls_len, - signer_infos, signer_infos_len, - &data, &datalen) != 1 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - - - - return 1; -} - -/* -由于这组接口提供相对简化的接口,因此不是必须的输入都被忽略了 -*/ -int cms_sign_and_seal(const SM2_KEY *sign_keys, - const X509_CERTIFICATE *sign_certs, size_t sign_count, - const X509_CERTIFICATE *rcpt_certs, size_t rcpt_count, - const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen) -{ - int content_type = CMS_data; - const uint8_t *shared_info1 = NULL; - const uint8_t *shared_info2 = NULL; - size_t shared_info1_len = 0, shared_info2_len = 0; - - const uint8_t *sign_crls = NULL; - size_t sign_crls_len = 0; - - *outlen = 0; - cms_signed_and_enveloped_data_sign_encrypt_to_der( - sign_keys, sign_certs, sign_count, - sign_crls, sign_crls_len, - rcpt_certs, rcpt_count, - content_type, in, inlen, + if ((ret = cms_enced_content_info_from_der(content_type, + enc_algor, iv, ivlen, &enced_content, &enced_content_len, shared_info1, shared_info1_len, shared_info2, shared_info2_len, - &out, outlen); + in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + + if (*enc_algor != OID_sm4_cbc) { + error_print(); + return -1; + } + if (*ivlen != SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + if (keylen != SM4_KEY_SIZE) { + error_print(); + return -1; + } + + sm4_set_decrypt_key(&sm4_key, key); + if (sm4_cbc_padding_decrypt(&sm4_key, *iv, enced_content, enced_content_len, + content, content_len) != 1) { + memset(&sm4_key, 0, sizeof(SM4_KEY)); + return -1; + } + memset(&sm4_key, 0, sizeof(SM4_KEY)); return 1; } -/* -1997 int cms_signed_and_enveloped_data_decrypt_verify_from_der( -1998 const SM2_KEY *dec_key, const X509_CERTIFICATE *dec_cert, -1999 const uint8_t **rcpt_infos, size_t *rcpt_infos_len, -2000 const uint8_t **dgst_algors, size_t *dgst_algors_len, -2001 int *content_type, -2002 int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, -2003 const uint8_t **enced_content, size_t *enced_content_len, -2004 const uint8_t **shared_info1, size_t *shared_info1_len, -2005 const uint8_t **shared_info2, size_t *shared_info2_len, -2006 const uint8_t **certs, size_t *certs_len, -2007 const uint8_t **crls, size_t *crls_len, -2008 const uint8_t **signer_infos, size_t *signer_infos_len) -*/ -int cms_open_and_verify( - const SM2_KEY *sm2_key, const X509_CERTIFICATE *cert, - const uint8_t *in, size_t inlen, - int *content_type, uint8_t *out, size_t *outlen) -{ - return -1; -} + + + + + + + + + + + + diff --git a/src/debug.c b/src/debug.c index 609dca28..465520bc 100644 --- a/src/debug.c +++ b/src/debug.c @@ -120,6 +120,19 @@ int format_bytes(FILE *fp, int format, int indent, const char *str, const uint8_ } +int format_string(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + while (ind--) { + fprintf(fp, " "); + } + fprintf(fp, "%s: ", label); + while (dlen--) { + fprintf(fp, "%c", *d++); + } + fprintf(fp, "\n"); + return 1; +} + int tls_trace(int format, int indent, const char *str, ...) { FILE *fp = stderr; diff --git a/src/digest.c b/src/digest.c index 2f550360..e1f1036c 100644 --- a/src/digest.c +++ b/src/digest.c @@ -53,13 +53,8 @@ #include -int digest_nid(const DIGEST *digest) -{ - return digest->nid; -} - typedef struct { - int nid; + int oid; char *short_name; char *display_name; } DIGEST_TABLE; @@ -78,65 +73,44 @@ const char *digest_name(const DIGEST *digest) { int i; for (i = 0; i < sizeof(digest_table)/sizeof(digest_table[0]); i++) { - if (digest->nid == digest_table[i].nid) { + if (digest->oid == digest_table[i].oid) { return digest_table[i].short_name; } } return NULL; } -size_t digest_size(const DIGEST *digest) -{ - return digest->digest_size; -} - -size_t digest_block_size(const DIGEST *digest) -{ - return digest->block_size; -} - -int digest_ctx_init(DIGEST_CTX *ctx) -{ - memset(ctx, 0, sizeof(DIGEST_CTX)); - return 1; -} - -void digest_ctx_cleanup(DIGEST_CTX *ctx) -{ - memset(ctx, 0, sizeof(DIGEST_CTX)); -} - int digest_init(DIGEST_CTX *ctx, const DIGEST *algor) { + memset(ctx, 0, sizeof(DIGEST_CTX)); ctx->digest = algor; ctx->digest->init(ctx); return 1; } -int digest_update(DIGEST_CTX *ctx, const unsigned char *data, size_t datalen) +int digest_update(DIGEST_CTX *ctx, const uint8_t *data, size_t datalen) { ctx->digest->update(ctx, data, datalen); return 1; } -int digest_finish(DIGEST_CTX *ctx, unsigned char *dgst, size_t *dgstlen) +int digest_finish(DIGEST_CTX *ctx, uint8_t *dgst, size_t *dgstlen) { ctx->digest->finish(ctx, dgst); *dgstlen = ctx->digest->digest_size; return 1; } -int digest(const DIGEST *digest, const unsigned char *data, size_t datalen, - unsigned char *dgst, size_t *dgstlen) +int digest(const DIGEST *digest, const uint8_t *data, size_t datalen, + uint8_t *dgst, size_t *dgstlen) { DIGEST_CTX ctx; - if (!digest_ctx_init(&ctx) - || !digest_init(&ctx, digest) + if (!digest_init(&ctx, digest) || !digest_update(&ctx, data, datalen) || !digest_finish(&ctx, dgst, dgstlen)) { return 0; } - digest_ctx_cleanup(&ctx); + memset(&ctx, 0, sizeof(DIGEST_CTX)); return 1; } @@ -173,7 +147,7 @@ static int sm3_digest_init(DIGEST_CTX *ctx) return 1; } -static int sm3_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen) +static int sm3_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) { if (!ctx || (!in && inlen != 0)) { return 0; @@ -182,7 +156,7 @@ static int sm3_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t in return 1; } -static int sm3_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sm3_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { if (!ctx || !dgst) { return 0; @@ -218,7 +192,7 @@ static int md5_digest_init(DIGEST_CTX *ctx) return 1; } -static int md5_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen) +static int md5_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) { if (!ctx || (!in && inlen != 0)) { return 0; @@ -227,7 +201,7 @@ static int md5_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t in return 1; } -static int md5_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int md5_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { if (!ctx || !dgst) { return 0; @@ -263,7 +237,7 @@ static int sha1_digest_init(DIGEST_CTX *ctx) return 1; } -static int sha1_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen) +static int sha1_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) { if (!ctx || (!in && inlen != 0)) { return 0; @@ -272,7 +246,7 @@ static int sha1_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t i return 1; } -static int sha1_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sha1_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { if (!ctx || !dgst) { return 0; @@ -308,7 +282,7 @@ static int sha224_digest_init(DIGEST_CTX *ctx) return 1; } -static int sha224_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen) +static int sha224_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) { if (!ctx || (!in && inlen != 0)) { return 0; @@ -317,7 +291,7 @@ static int sha224_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t return 1; } -static int sha224_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sha224_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { if (!ctx || !dgst) { return 0; @@ -350,7 +324,7 @@ static int sha256_digest_init(DIGEST_CTX *ctx) return 1; } -static int sha256_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen) +static int sha256_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) { if (!ctx || (!in && inlen != 0)) { return 0; @@ -359,7 +333,7 @@ static int sha256_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t return 1; } -static int sha256_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sha256_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { if (!ctx || !dgst) { return 0; @@ -393,7 +367,7 @@ static int sha384_digest_init(DIGEST_CTX *ctx) return 1; } -static int sha384_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen) +static int sha384_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) { if (!ctx || (!in && inlen != 0)) { return 0; @@ -402,7 +376,7 @@ static int sha384_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t return 1; } -static int sha384_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sha384_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { if (!ctx || !dgst) { return 0; @@ -436,7 +410,7 @@ static int sha512_digest_init(DIGEST_CTX *ctx) return 1; } -static int sha512_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t inlen) +static int sha512_digest_update(DIGEST_CTX *ctx, const uint8_t *in, size_t inlen) { if (!ctx || (!in && inlen != 0)) { return 0; @@ -445,7 +419,7 @@ static int sha512_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t return 1; } -static int sha512_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sha512_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { if (!ctx || !dgst) { return 0; @@ -470,9 +444,9 @@ const DIGEST *DIGEST_sha512(void) } -static int sha512_224_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sha512_224_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { - unsigned char buf[SHA512_DIGEST_SIZE]; + uint8_t buf[SHA512_DIGEST_SIZE]; if (!ctx || !dgst) { return 0; } @@ -498,9 +472,9 @@ const DIGEST *DIGEST_sha512_224(void) } -static int sha512_256_digest_finish(DIGEST_CTX *ctx, unsigned char *dgst) +static int sha512_256_digest_finish(DIGEST_CTX *ctx, uint8_t *dgst) { - unsigned char buf[SHA512_DIGEST_SIZE]; + uint8_t buf[SHA512_DIGEST_SIZE]; if (!ctx || !dgst) { return 0; } diff --git a/src/gf128.c b/src/gf128.c index 1b77f92f..f5d57779 100644 --- a/src/gf128.c +++ b/src/gf128.c @@ -68,7 +68,8 @@ gf128_t gf128_zero(void) gf128_t gf128_from_hex(const char *s) { uint8_t bin[16]; - hex2bin(s, strlen(s), bin); + size_t len; + hex_to_bytes(s, strlen(s), bin, &len); return gf128_from_bytes(bin); } @@ -76,7 +77,8 @@ int gf128_equ_hex(gf128_t a, const char *s) { uint8_t bin1[16]; uint8_t bin2[16]; - hex2bin(s, strlen(s), bin1); + size_t len; + hex_to_bytes(s, strlen(s), bin1, &len); gf128_to_bytes(a, bin2); return memcmp(bin1, bin2, sizeof(bin1)) == 0; } diff --git a/src/hash_drbg.c b/src/hash_drbg.c index e559b1ae..20bcb214 100644 --- a/src/hash_drbg.c +++ b/src/hash_drbg.c @@ -66,8 +66,6 @@ static int hash_df(const DIGEST *digest, const uint8_t *in, size_t inlen, counter = 0x01; PUTU32(outbits, (uint32_t)outlen << 3); - digest_ctx_init(&ctx); - while (outlen > 0) { if (!digest_init(&ctx, digest) || !digest_update(&ctx, &counter, sizeof(counter)) @@ -89,7 +87,7 @@ static int hash_df(const DIGEST *digest, const uint8_t *in, size_t inlen, ret = 1; end: - digest_ctx_cleanup(&ctx); + memset(&ctx, 0, sizeof(ctx)); memset(dgst, 0, sizeof(dgst)); return ret; } @@ -111,7 +109,7 @@ int hash_drbg_init(HASH_DRBG *drbg, const DIGEST *digest, drbg->digest = digest; /* set seedlen */ - if (digest_size(digest) <= 32) { + if (digest->digest_size <= 32) { drbg->seedlen = HASH_DRBG_SM3_SEED_SIZE; } else { drbg->seedlen = HASH_DRBG_SHA512_SEED_SIZE; @@ -240,8 +238,6 @@ static int drbg_hashgen(HASH_DRBG *drbg, size_t outlen, uint8_t *out) uint8_t dgst[DIGEST_MAX_SIZE]; size_t len; - digest_ctx_init(&ctx); - /* data = V */ memcpy(data, drbg->V, drbg->seedlen); @@ -289,8 +285,6 @@ int hash_drbg_generate(HASH_DRBG *drbg, return 0; } - digest_ctx_init(&ctx); - if (additional) { /* w = Hash (0x02 || V || additional_input) */ prefix = 0x02; @@ -336,7 +330,7 @@ int hash_drbg_generate(HASH_DRBG *drbg, ret = 1; end: - digest_ctx_cleanup(&ctx); + memset(&ctx, 0, sizeof(ctx)); memset(T, 0, sizeof(T)); memset(dgst, 0, sizeof(dgst)); return ret; diff --git a/src/hkdf.c b/src/hkdf.c index 6a851e7f..b44027ba 100644 --- a/src/hkdf.c +++ b/src/hkdf.c @@ -93,7 +93,7 @@ int hkdf_extract(const DIGEST *digest, const uint8_t *salt, size_t saltlen, if (!salt || saltlen == 0) { uint8_t zeros[DIGEST_MAX_SIZE] = {0}; - if (hmac_init(&hmac_ctx, digest, zeros, digest_size(digest)) != 1) { + if (hmac_init(&hmac_ctx, digest, zeros, digest->digest_size) != 1) { error_print(); return -1; } diff --git a/src/hmac.c b/src/hmac.c index ff5c727a..d8b3f9cb 100644 --- a/src/hmac.c +++ b/src/hmac.c @@ -55,7 +55,7 @@ #define OPAD 0x5C -int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, size_t keylen) +int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const uint8_t *key, size_t keylen) { uint8_t i_key[DIGEST_MAX_BLOCK_SIZE] = {0}; uint8_t o_key[DIGEST_MAX_BLOCK_SIZE] = {0}; @@ -69,7 +69,7 @@ int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, siz ctx->digest = digest; - blocksize = digest_block_size(digest); + blocksize = digest->block_size; if (keylen <= blocksize) { memcpy(i_key, key, keylen); memcpy(o_key, key, keylen); @@ -95,7 +95,7 @@ int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, siz return 1; } -int hmac_update(HMAC_CTX *ctx, const unsigned char *data, size_t datalen) +int hmac_update(HMAC_CTX *ctx, const uint8_t *data, size_t datalen) { if (!ctx || (!data && datalen != 0)) { error_print(); @@ -108,7 +108,7 @@ int hmac_update(HMAC_CTX *ctx, const unsigned char *data, size_t datalen) return 1; } -int hmac_finish(HMAC_CTX *ctx, unsigned char *mac, size_t *maclen) +int hmac_finish(HMAC_CTX *ctx, uint8_t *mac, size_t *maclen) { if (digest_finish(&ctx->digest_ctx, mac, maclen) != 1) { error_print(); @@ -140,9 +140,9 @@ int hmac_finish_and_verify(HMAC_CTX *ctx, const uint8_t *mac, size_t maclen) return 1; } -int hmac(const DIGEST *digest, const unsigned char *key, size_t keylen, - const unsigned char *data, size_t datalen, - unsigned char *mac, size_t *maclen) +int hmac(const DIGEST *digest, const uint8_t *key, size_t keylen, + const uint8_t *data, size_t datalen, + uint8_t *mac, size_t *maclen) { int ret = 0; HMAC_CTX ctx; diff --git a/src/oid.c b/src/oid.c index 89204a8f..8c6ac13a 100644 --- a/src/oid.c +++ b/src/oid.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -601,362 +601,3 @@ void asn1_oid_to_octets(int oid, uint8_t *out, size_t *outlen) assert(0); } } - -// asn1_oid_from_octets 不返回错误值,只返回 OID_undef -// 但是数据编码仍可能是非法的 -// 如果返回 OID_undef,需要通过 asn1_oid_nodes_from_octets 判断格式是否正确 -int asn1_oid_from_octets(const uint8_t *in, size_t inlen) -{ - int ret = OID_undef; - if (inlen == sizeof(DER_x9_62_ecPublicKey) - && memcmp(DER_x9_62_ecPublicKey, in, inlen) == 0) { - return OID_x9_62_ecPublicKey; - } - - if (inlen >= sizeof(DER_x9_62_ecPublicKey) - && memcmp(in, DER_x9_62_ecPublicKey, sizeof(DER_x9_62_ecPublicKey)) == 0) { - if (inlen == sizeof(DER_x9_62_ecPublicKey)) - ret = OID_x9_62_ecPublicKey; - else ret = asn1_x9_62_curve_oid_from_octets(in, inlen); - } else if (inlen > sizeof(DER_sm) - && memcmp(in, DER_sm, sizeof(DER_sm)) == 0) { - ret = asn1_sm_oid_from_octets(in, inlen); - } else if (inlen > sizeof(DER_secg_curve) - && memcmp(in, DER_secg_curve, sizeof(DER_secg_curve)) == 0) { - ret = asn1_secg_curve_oid_from_octets(in, inlen); - } else if (inlen > sizeof(DER_x509) - && memcmp(in, DER_x509, sizeof(DER_x509)) == 0) { - ret = asn1_x509_oid_from_octets(in, inlen); - } else { - /* - int i; - error_print("unknown der\n"); - print_der(in, inlen); - printf("\n"); - */ - return OID_undef; - } - - if (ret < 0) { - error_print(); - } - return ret; -} - -// 输出长度不固定,并且被多次重复调用,因此提供 **out 形式的参数 -static void uint_to_base128(uint32_t a, uint8_t **out, size_t *outlen) -{ - uint8_t buf[5]; - int n = 0; - - buf[n++] = a & 0x7f; - a >>= 7; - - while (a) { - buf[n++] = 0x80 | (a & 0x7f); - a >>= 7; - } - - while (n--) { - if (out) - *(*out)++ = buf[n]; - (*outlen)++; - } -} - -// 实际上我们在解析的时候是不知道具体在哪里结束的 -// 解析是有可能出错的,如果没有发现最后一个0开头的字节就出错了 -// 还有值太大也会出错,我们最多读取5个字节 -// { 0x81, 0x82 } -// { 0x81, 0x82, 0x83, 0x84, 0x85, 0x06 } -static int uint_from_base128(uint32_t *a, const uint8_t **in, size_t *inlen) -{ - uint8_t buf[5]; - int n = 0; - int i; - - for (;;) { - if ((*inlen)-- < 1 || n >= 5) { - return -1; - } - buf[n] = *(*in)++; - if ((buf[n++] & 0x80) == 0) { - break; - } - } - - // 32 - 7*4 = 4, so the first byte should be like 1000bbbb - if (n == 5 && (buf[0] & 0x70)) { - return -1; - } - - *a = 0; - for (i = 0; i < n; i++) { - *a = ((*a) << 7) | (buf[i] & 0x7f); - } - - return 1; -} - -int asn1_oid_nodes_to_octets(const uint32_t *nodes, size_t nodes_count, uint8_t *out, size_t *outlen) -{ - if (nodes_count < 2 || nodes_count > 32) { - return -1; - } - if (out) - *out++ = (uint8_t)(nodes[0] * 40 + nodes[1]); - (*outlen) = 1; - nodes += 2; - nodes_count -= 2; - - while (nodes_count--) { - uint_to_base128(*nodes++, &out, outlen); - } - return 1; -} - -// 因为这个函数总是被asn1函数调用的,因此给的输入数据长度是已知的 -int asn1_oid_nodes_from_octets(uint32_t *nodes, size_t *nodes_count, const uint8_t *in, size_t inlen) -{ - size_t count = 0; - const uint8_t *p = in; - size_t len = inlen; - - if (!nodes || !nodes_count || !in || inlen <= 0) { - error_print(); - return -1; - } - - if (inlen < 1) { - error_print(); - return -1; - } - - // FIXME: 需要支持 nodes = NULL 吗? - if (nodes) { - *nodes++ = (*in) / 40; - *nodes++ = (*in) % 40; - } - in++; - inlen--; - count += 2; - - while (inlen) { - uint32_t val; - if (count > 32) { - return -1; - } - if (uint_from_base128(&val, &in, &inlen) < 0) { - return -1; - } - if (nodes) { - *nodes++ = val; - } - count++; - } - - *nodes_count = count; - return 1; -} - -// 调用方应提供一个已知的 OID 名字,否则函数会返回错误,而非返回 OID_undef -int asn1_object_identifier_from_name(int *oid, const char *name) -{ - if (!oid || !name) { - return -1; - } - - if ((*oid = asn1_sm_oid_from_name(name)) != OID_undef) - return 1; - if ((*oid = asn1_x9_62_curve_oid_from_name(name)) != OID_undef) - return 1; - if ((*oid = asn1_secg_curve_oid_from_name(name)) != OID_undef) - return 1; - if ((*oid = asn1_x509_oid_from_name(name)) != OID_undef) - return 1; - - return 1; -} - -const char *asn1_object_identifier_name(int oid) -{ - if (oid < 0) { - return NULL; - } else if (oid == OID_undef) { - return "undef"; - } else if (oid <= OID_rsasign_with_sm3) { - return asn1_sm_oid_name(oid); - } else if (oid <= OID_x9_62_ecPublicKey) { // FIXME: 目前单独处理,后续应增加公钥类型 OID 集合 - return "x9_62_ecPublicKey"; - } else if (oid <= OID_prime256v1) { - return asn1_x9_62_curve_oid_name(oid); - } else if (oid <= OID_secp521r1) { - return asn1_secg_curve_oid_name(oid); - } else if (oid <= OID_at_role) { - return asn1_x509_oid_name(oid); - } else { - // FIXME: 还有后续的一些X.509 OID没有支持 - return NULL; - } -} - -const char *asn1_object_identifier_description(int oid) -{ - if (oid < 0) { - return NULL; - } else if (oid == OID_undef) { - return ""; - } else if (oid <= OID_rsasign_with_sm3) { - return asn1_sm_oid_description(oid); - } else if (oid <= OID_x9_62_ecPublicKey) { // FIXME: 目前单独处理,后续应增加公钥类型 OID 集合 - return "x9_62_ecPublicKey"; - } else if (oid <= OID_prime256v1) { - return asn1_x9_62_curve_oid_description(oid); - } else if (oid <= OID_secp521r1) { - return asn1_secg_curve_oid_description(oid); - } else if (oid <= OID_at_role) { - return asn1_x509_oid_description(oid); - } - // FIXME: 还有后续的一些X.509 OID没有支持 - return NULL; -} - - -// FIXME: 这个测试函数都应该挪到测试目录中去 - - - -// 测试 oid_nodes 编解码是否正确 -// FIXME: 还应该增加一些外部的测试用例 -int test_asn1_oid_nodes(void) -{ - int oid; - uint8_t octets[64]; - uint8_t buf[64]; - uint32_t nodes[32]; - size_t octetslen, buflen, nodes_count; - - for (oid = 1; oid <= OID_at_role; oid++) { - int i; - asn1_oid_to_octets(oid, octets, &octetslen); - asn1_oid_nodes_from_octets(nodes, &nodes_count, octets, octetslen); - asn1_oid_nodes_to_octets(nodes, nodes_count, buf, &buflen); - if (buflen != octetslen || memcmp(octets, buf, buflen) != 0) { - fprintf(stderr, "%s %d: oid = %d error\n", __FILE__, __LINE__, oid); - } - - printf("%d : ", oid); - for (i = 0; i < nodes_count; i++) { - printf("%d ", (int)nodes[i]); - } - printf("\n"); - } - - return 1; -} - -int test_asn1_oid(void) -{ - uint8_t buf[1024]; - uint8_t *p = buf; - size_t len =0; - int oid; - int i; - - uint32_t nodes[32]; - size_t nodes_count; - - test_asn1_oid_nodes(); - - for (i = 1; i <= OID_at_role; i++) { - int j; - asn1_oid_to_octets(i, buf, &len); - oid = asn1_oid_from_octets(buf, len); - printf("%d %s %s ", oid, asn1_object_identifier_name(oid), asn1_object_identifier_description(oid)); - - asn1_oid_nodes_from_octets(nodes, &nodes_count, buf, len); - for (j = 0; j < nodes_count; j++) { - printf("%d.", nodes[j]); - } - printf("\n"); - } - - return 1; -} - -int test_asn1_object_identifier_to_der(int oid) -{ - uint8_t buf[64] = {0}; - const uint8_t *cp = buf; - uint8_t *p = buf; - size_t len = 0, i; - uint32_t nodes[32] = {0}; - size_t nodes_count; - int roid; - - if (asn1_object_identifier_to_der(oid, NULL, 0, &p, &len) != 1) { - error_print(); - return 0; - } - printf("%d : %s : ", oid, asn1_object_identifier_name(oid)); - print_der(buf, len); - - - if (asn1_object_identifier_from_der(&roid, nodes, &nodes_count, &cp, &len) != 1) { - error_print(); - return 0; - } - printf(" : "); - print_nodes(nodes, nodes_count); - printf("\n"); - - if (roid != oid) { - error_print(); - return -1; - } - if (len != 0) { - error_print(); - return -1; - } - return 1; -} - -int test_asn1_object_identifier(void) -{ - uint8_t buf[2048]; - const uint8_t *cp = buf; - uint8_t *p = buf; - size_t len = 0; - uint32_t nodes[32] = {0}; - size_t nodes_count; - int oid; - int i; - - // 分别测试每个oid分别编解码是否正确 - for (oid = 1; oid <= OID_at_role; oid++) { - if (test_asn1_object_identifier_to_der(oid) < 0) { - error_print(); - return -1; - } - } - - // 将全部oid编码后再解码 - for (oid = 1; oid <= OID_at_role; oid++) { - if (asn1_object_identifier_to_der(oid, NULL, 0, &p, &len) != 1) { - error_print(); - return -1; - } - } - printf("%s %d: All OIDs encoded length = %zu bytes\n", __FILE__, __LINE__, len); - print_der(buf, len); - printf("\n"); - - while (len) { - int ret; - if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &cp, &len) <= 0) { - break; - } - printf("%d %s\n", oid, asn1_object_identifier_name(oid)); - } - return 1; -} diff --git a/src/pem.c b/src/pem.c index 233dba75..987bfdf5 100644 --- a/src/pem.c +++ b/src/pem.c @@ -70,7 +70,7 @@ int pem_write(FILE *fp, const char *name, const uint8_t *data, size_t datalen) return ret; } -int pem_read(FILE *fp, const char *name, uint8_t *data, size_t *datalen) +int pem_read(FILE *fp, const char *name, uint8_t *data, size_t *datalen, size_t maxlen) { char line[80]; char begin_line[80]; diff --git a/src/pkcs8.c b/src/pkcs8.c index c3c19380..24aff4d7 100644 --- a/src/pkcs8.c +++ b/src/pkcs8.c @@ -71,6 +71,10 @@ PBKDF2-params ::= SEQUENCE { */ +static const uint32_t oid_hmac_sm3[] = { 1,2 }; +static const size_t oid_hmac_sm3_count = sizeof(oid_hmac_sm3)/sizeof(oid_hmac_sm3[0]); + + int pbkdf2_params_to_der( const uint8_t *salt, size_t saltlen, int iter, @@ -103,7 +107,7 @@ int pbkdf2_params_to_der( if (asn1_octet_string_to_der(salt, saltlen, NULL, &len) != 1 || asn1_int_to_der(iter, NULL, &len) != 1 || asn1_int_to_der(keylen, NULL, &len) < 0 - || asn1_object_identifier_to_der(prf, NULL, 0, NULL, &prflen) != 1 + || asn1_object_identifier_to_der(oid_hmac_sm3, oid_hmac_sm3_count, NULL, &prflen) != 1 || asn1_null_to_der(NULL, &prflen) != 1 || asn1_sequence_to_der(NULL, prflen, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 @@ -111,7 +115,7 @@ int pbkdf2_params_to_der( || asn1_int_to_der(iter, out, outlen) != 1 || asn1_int_to_der(keylen, out, outlen) < 0 || asn1_sequence_header_to_der(prflen, out, outlen) != 1 - || asn1_object_identifier_to_der(prf, NULL, 0, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_hmac_sm3, oid_hmac_sm3_count, out, outlen) != 1 || asn1_null_to_der(out, outlen) != 1) { error_print(); return -1; @@ -155,16 +159,22 @@ int pbkdf2_params_from_der( if (algo) { uint32_t nodes[32]; size_t nodes_count; - if (asn1_object_identifier_from_der(prf, nodes, &nodes_count, &algo, &algolen) != 1 + + if (asn1_object_identifier_from_der(nodes, &nodes_count, &algo, &algolen) != 1 || asn1_null_from_der(&algo, &algolen) != 1 || algolen > 0) { error_print(); return -1; } - if (*prf != OID_hmac_sm3) { + if (nodes_count == oid_hmac_sm3_count + && memcmp(nodes, oid_hmac_sm3, sizeof(oid_hmac_sm3)) == 0) { + *prf = OID_hmac_sm3; + } else { + *prf = OID_undef; error_print(); return -1; } + } else { //*prf = OID_hmacWithSHA1; error_print(); @@ -174,6 +184,9 @@ int pbkdf2_params_from_der( return 1; } +static const uint32_t oid_pbkdf2[] = { 1, 2, 840, 113549, 1, 5, 12 }; +static const size_t oid_pbkdf2_count = sizeof(oid_pbkdf2)/sizeof(oid_pbkdf2[0]); + int pbkdf2_algor_to_der( const uint8_t *salt, size_t saltlen, int iter, @@ -182,13 +195,11 @@ int pbkdf2_algor_to_der( uint8_t **out, size_t *outlen) { size_t len = 0; - uint32_t pbkdf2[] = { 1, 2, 840, 113549, 1, 5, 12 }; - size_t pbkdf2_count = sizeof(pbkdf2)/sizeof(pbkdf2[0]); - if (asn1_object_identifier_to_der(OID_undef, pbkdf2, pbkdf2_count, NULL, &len) != 1 + if (asn1_object_identifier_to_der(oid_pbkdf2, oid_pbkdf2_count, NULL, &len) != 1 || pbkdf2_params_to_der(salt, saltlen, iter, keylen, prf, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(OID_undef, pbkdf2, pbkdf2_count, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_pbkdf2, oid_pbkdf2_count, out, outlen) != 1 || pbkdf2_params_to_der(salt, saltlen, iter, keylen, prf, out, outlen) != 1) { error_print(); return -1; @@ -206,8 +217,6 @@ int pbkdf2_algor_from_der( int ret; const uint8_t *data; size_t datalen; - uint32_t pbkdf2[] = { 1, 2, 840, 113549, 1, 5, 12 }; - size_t pbkdf2_count = sizeof(pbkdf2)/sizeof(pbkdf2[0]); int oid; uint32_t nodes[32]; size_t nodes_count; @@ -216,14 +225,15 @@ int pbkdf2_algor_from_der( if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1 + + if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1 || pbkdf2_params_from_der(salt, saltlen, iter, keylen, prf, &data, &datalen) != 1 || datalen > 0) { error_print(); return -1; } - if (oid != OID_undef || nodes_count != pbkdf2_count - || memcmp(nodes, pbkdf2, sizeof(pbkdf2)) != 0) { + if (oid != OID_undef || nodes_count != oid_pbkdf2_count + || memcmp(nodes, oid_pbkdf2, sizeof(oid_pbkdf2)) != 0) { error_print(); return -1; } @@ -232,8 +242,8 @@ int pbkdf2_algor_from_der( return 1; } -static uint32_t sm4_cbc_nodes[] = { 1, 2, 156, 10197, 1, 104, 2 }; -static size_t sm4_cbc_nodes_count = sizeof(sm4_cbc_nodes)/sizeof(sm4_cbc_nodes[0]); +static const uint32_t oid_sm4_cbc[] = { 1, 2, 156, 10197, 1, 104, 2 }; +static const size_t oid_sm4_cbc_count = sizeof(oid_sm4_cbc)/sizeof(oid_sm4_cbc[0]); // 这个应该提取到外面,和digest_algor, encryption_algor, sign_algor 之类的放到一起 @@ -245,10 +255,10 @@ int pbes2_enc_algor_to_der(int cipher, const uint8_t *iv, size_t ivlen, uint8_t error_print(); return -1; } - if (asn1_object_identifier_to_der(OID_undef, sm4_cbc_nodes, sm4_cbc_nodes_count, NULL, &len) != 1 + if (asn1_object_identifier_to_der(oid_sm4_cbc, oid_sm4_cbc_count, NULL, &len) != 1 || asn1_octet_string_to_der(iv, ivlen, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(OID_undef, sm4_cbc_nodes, sm4_cbc_nodes_count, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_sm4_cbc, oid_sm4_cbc_count, out, outlen) != 1 || asn1_octet_string_to_der(iv, ivlen, out, outlen) != 1) { error_print(); return -1; @@ -268,26 +278,25 @@ int pbes2_enc_algor_from_der(int *cipher, const uint8_t **iv, size_t *ivlen, con if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(cipher, nodes, &nodes_count, &data, &datalen) != 1 + + if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1 || asn1_octet_string_from_der(iv, ivlen, &data, &datalen) != 1 - || datalen > 0) { + || asn1_length_is_zero(datalen) != 1) { error_print(); return -1; } - if (*cipher == OID_undef) { - if (nodes_count == sm4_cbc_nodes_count - && memcmp(nodes, sm4_cbc_nodes, sizeof(sm4_cbc_nodes)) == 0) { - *cipher = OID_sm4_cbc; - } else { - size_t i; - error_print(); - for (i = 0; i < nodes_count; i++) { - fprintf(stderr, " %d", nodes[i]); - } - fprintf(stderr, "\n"); - return -1; + + if (asn1_object_identifier_equ(nodes, nodes_count, oid_sm4_cbc, oid_sm4_cbc_count) != 1) { + size_t i; + *cipher = OID_undef; + error_print(); + for (i = 0; i < nodes_count; i++) { + fprintf(stderr, " %d", nodes[i]); } + fprintf(stderr, "\n"); + return -1; } + *cipher = OID_sm4_cbc; // FIXME: 检查ivlen return 1; @@ -345,6 +354,10 @@ int pbes2_params_from_der( return 1; } + +static const uint32_t oid_pbes2[] = { 1, 2, 840, 113549, 1, 5, 13 }; +static const size_t oid_pbes2_count = sizeof(oid_pbes2)/sizeof(oid_pbes2[0]); + int pbes2_algor_to_der( const uint8_t *salt, size_t saltlen, int iter, @@ -354,13 +367,11 @@ int pbes2_algor_to_der( uint8_t **out, size_t *outlen) { size_t len = 0; - uint32_t pbes2[] = { 1, 2, 840, 113549, 1, 5, 13 }; - size_t pbes2_count = sizeof(pbes2)/sizeof(pbes2[0]); - if (asn1_object_identifier_to_der(OID_undef, pbes2, pbes2_count, NULL, &len) != 1 + if (asn1_object_identifier_to_der(oid_pbes2, oid_pbes2_count, NULL, &len) != 1 || pbes2_params_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(OID_undef, pbes2, pbes2_count, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_pbes2, oid_pbes2_count, out, outlen) != 1 || pbes2_params_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, out, outlen) != 1) { error_print(); return -1; @@ -379,8 +390,6 @@ int pbes2_algor_from_der( int ret; const uint8_t *data; size_t datalen; - uint32_t pbes2[] = { 1, 2, 840, 113549, 1, 5, 13 }; - size_t pbes2_count = sizeof(pbes2)/sizeof(pbes2[0]); int oid; uint32_t nodes[32]; size_t nodes_count; @@ -389,17 +398,15 @@ int pbes2_algor_from_der( if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1 + + if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1 || pbes2_params_from_der(salt, saltlen, iter, prf, cipher, iv, ivlen, &data, &datalen) != 1 || datalen > 0) { error_print(); return -1; } - if (oid != OID_undef) { - error_print(); - return -1; - } - if (nodes_count != pbes2_count && memcmp(nodes, pbes2, sizeof(pbes2)) != 0) { + if (nodes_count != oid_pbes2_count + && memcmp(nodes, oid_pbes2, sizeof(oid_pbes2)) != 0) { error_print(); return -1; } @@ -569,7 +576,7 @@ int sm2_enced_private_key_info_from_pem(SM2_KEY *key, const char *pass, FILE *fp const uint8_t *attrs; size_t attrslen; - if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len) != 1) { + if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len, sizeof(buf)) != 1) { error_print(); return -1; } diff --git a/src/rc4.c b/src/rc4.c index 9ebee294..2cc3a33b 100644 --- a/src/rc4.c +++ b/src/rc4.c @@ -51,12 +51,12 @@ #include #include -void rc4_set_key(RC4_STATE *state, const unsigned char *key, size_t keylen) +void rc4_init(RC4_STATE *state, const uint8_t *key, size_t keylen) { int i, j; - unsigned char *s = state->d; - unsigned char k[256]; - unsigned char temp; + uint8_t *s = state->d; + uint8_t k[256]; + uint8_t temp; /* expand key */ for (i = 0; i < keylen; i++) { @@ -86,10 +86,10 @@ void rc4_set_key(RC4_STATE *state, const unsigned char *key, size_t keylen) memset(k, 0, sizeof(k)); } -void rc4_generate_keystream(RC4_STATE *state, size_t outlen, unsigned char *out) +void rc4_generate_keystream(RC4_STATE *state, size_t outlen, uint8_t *out) { int i = 0, j = 0; - unsigned char *s = state->d; + uint8_t *s = state->d; int oi; int temp; @@ -109,9 +109,9 @@ void rc4_generate_keystream(RC4_STATE *state, size_t outlen, unsigned char *out) } } -unsigned char rc4_generate_keybyte(RC4_STATE *state) +uint8_t rc4_generate_keybyte(RC4_STATE *state) { - unsigned char out[1]; + uint8_t out[1]; rc4_generate_keystream(state, 1, out); return out[0]; } diff --git a/src/sm2_algo.c b/src/sm2_algo.c index 5165309c..a1a36901 100644 --- a/src/sm2_algo.c +++ b/src/sm2_algo.c @@ -1251,13 +1251,13 @@ static int point_test(void) return err; } -int sm2_algo_selftest(void) +int sm2_selftest(void) { point_test(); return 0; } -int sm2_keygen(SM2_KEY *key) +int sm2_key_generate(SM2_KEY *key) { bignum_t x; bignum_t y; diff --git a/src/sm2_asn1.c b/src/sm2_asn1.c index 0aea2add..30460ace 100644 --- a/src/sm2_asn1.c +++ b/src/sm2_asn1.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,9 @@ #include #include +// sm2 curve 1.2.156.10197.1.301 + + void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33]) { *out++ = (P->y[31] & 0x01) ? 0x03 : 0x02; @@ -136,14 +139,12 @@ int sm2_signature_from_der(SM2_SIGNATURE *sig, const uint8_t **in, size_t *inlen return 1; } -/* -SM2Cipher ::= SEQUENCE { - XCoordinate INTEGER, // 变长 - YCoordinate INTEGER, // 变长 - HASH OCTET STRING SIZE(32), - CipherText OCTET STRING +int sm2_ciphertext_size(size_t inlen, size_t *outlen) +{ + *outlen = sizeof(SM2_CIPHERTEXT)-1+inlen; + return 1; } -*/ + int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen) { size_t len = 0; @@ -187,23 +188,12 @@ int sm2_ciphertext_from_der(SM2_CIPHERTEXT *a, const uint8_t **in, size_t *inlen return 1; } -/* -from RFC 5915 -ECPrivateKey ::= SEQUENCE { - version INTEGER, -- value MUST be ecPrivkeyVer1(1) - privateKey OCTET STRING, -- big endian encoding of integer - parameters [0] EXPLICIT ECParameters OPTIONAL, - -- ONLY namedCurve OID is permitted, by RFC 5480 - -- MUST always include this field, by RFC 5915 - publicKey [1] EXPLICIT BIT STRING OPTIONAL - -- SHOULD always include this field, by RFC 5915 -} -ECParameters ::= CHOICE { - namedCurve OBJECT IDENTIFIER -} -*/ +// TODO: sm2, ecPublicKey 这些公用的OID应该提取到一个地方 +static const uint32_t oid_sm2[] = { 1,2,156,10197,1,301 }; +static const size_t oid_sm2_count = sizeof(oid_sm2)/sizeof(oid_sm2[0]); + int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen) { int version = 1; @@ -216,7 +206,7 @@ int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen) asn1_int_to_der(version, NULL, &len); asn1_octet_string_to_der(key->private_key, 32, NULL, &len); - asn1_object_identifier_to_der(OID_sm2, NULL, 0, NULL, ¶ms_len); + asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, NULL, ¶ms_len); asn1_explicit_to_der(0, NULL, params_len, NULL, &len); asn1_bit_string_to_der(public_key, sizeof(public_key) * 8, NULL, &pubkey_len); asn1_explicit_to_der(1, NULL, pubkey_len, NULL, &len); @@ -225,7 +215,7 @@ int sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen) asn1_int_to_der(version, out, outlen); asn1_octet_string_to_der(key->private_key, 32, out, outlen); asn1_explicit_header_to_der(0, params_len, out, outlen); - asn1_object_identifier_to_der(OID_sm2, NULL, 0, out, outlen); + asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, out, outlen); asn1_explicit_header_to_der(1, pubkey_len, out, outlen); asn1_bit_string_to_der(public_key, sizeof(public_key) * 8, out, outlen); @@ -266,21 +256,21 @@ int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen) error_print(); return -1; } - if (sm2_set_private_key(key, prikey) != 1) { + if (sm2_key_set_private_key(key, prikey) != 1) { error_print(); return -1; } if (params) { - int curve_oid; - uint32_t nodes[16]; + uint32_t nodes[16]; // FIXME: 这个长度不对啊! size_t nodes_count; - if (asn1_object_identifier_from_der(&curve_oid, nodes, &nodes_count, ¶ms, ¶ms_len) != 1 + if (asn1_object_identifier_from_der(nodes, &nodes_count, ¶ms, ¶ms_len) != 1 || params_len > 0) { error_print(); return -1; } - if (curve_oid != OID_sm2) { + if (nodes_count != oid_sm2_count + || memcmp(nodes, oid_sm2, sizeof(oid_sm2)) != 0) { error_print(); return -1; } @@ -307,19 +297,22 @@ int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen) return 1; } -/* -AlgorithmIdentifier ::= { - algorithm OBJECT IDENTIFIER { id-ecPublicKey }, - parameters OBJECT IDENTIFIER { id-sm2 } } -*/ + + +static const uint32_t oid_ec_public_key[] = { 1,2,840,10045,2,1 }; +static const size_t oid_ec_public_key_count = sizeof(oid_ec_public_key)/sizeof(oid_ec_public_key[0]); + int sm2_public_key_algor_to_der(uint8_t **out, size_t *outlen) { size_t len = 0; - asn1_object_identifier_to_der(OID_x9_62_ecPublicKey, NULL, 0, NULL, &len); - asn1_object_identifier_to_der(OID_sm2, NULL, 0, NULL, &len); - asn1_sequence_header_to_der(len, out, outlen); - asn1_object_identifier_to_der(OID_x9_62_ecPublicKey, NULL, 0, out, outlen); - asn1_object_identifier_to_der(OID_sm2, NULL, 0, out, outlen); + if (asn1_object_identifier_to_der(oid_ec_public_key, oid_ec_public_key_count, NULL, &len) != 1 + || asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_ec_public_key, oid_ec_public_key_count, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, out, outlen) != 1) { + error_print(); + return -1; + } return 1; } @@ -328,23 +321,20 @@ int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen) int ret; const uint8_t *data; size_t datalen; - int oid; - uint32_t nodes[16]; - size_t nodes_count = 16; + uint32_t nodes[ASN1_OID_MAX_NODES]; + size_t nodes_count; if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - - if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1 - || oid != OID_x9_62_ecPublicKey) { + if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1 + || asn1_object_identifier_equ(nodes, nodes_count, oid_ec_public_key, oid_ec_public_key_count) != 1) { error_print(); return -1; } - - if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1 - || oid != OID_sm2) { + if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1 + || asn1_object_identifier_equ(nodes, nodes_count, oid_sm2, oid_sm2_count) != 1) { error_print(); return -1; } @@ -355,16 +345,7 @@ int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen) return 1; } -/* -from RFC 5208 -PrivateKeyInfo ::= SEQUENCE { - version Version { v1(0) }, - privateKeyAlgorithm AlgorithmIdentifier, - privateKey OCTET STRING, -- DER-encoding of ECPrivateKey - attributes [0] IMPLICIT SET OF Attribute OPTIONAL -} -*/ int sm2_private_key_info_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen) { size_t len = 0; @@ -441,7 +422,7 @@ int sm2_private_key_info_from_pem(SM2_KEY *key, const uint8_t **attrs, size_t *a const uint8_t *cp = buf; size_t len; - if (pem_read(fp, "PRIVATE KEY", buf, &len) != 1) { + if (pem_read(fp, "PRIVATE KEY", buf, &len, sizeof(buf)) != 1) { error_print(); return -1; } @@ -452,12 +433,7 @@ int sm2_private_key_info_from_pem(SM2_KEY *key, const uint8_t **attrs, size_t *a return 1; } -/* -SubjectPublicKeyInfo ::= SEQUENCE { - algorithm AlgorithmIdentifier, - subjectPublicKey BIT STRING -- uncompressed octets of ECPoint -} -*/ + int sm2_public_key_info_to_der(const SM2_KEY *a, uint8_t **out, size_t *outlen) { size_t len = 0; @@ -502,7 +478,7 @@ int sm2_public_key_info_from_der(SM2_KEY *a, const uint8_t **in, size_t *inlen) return -1; } memset(a, 0, sizeof(SM2_KEY)); - if (sm2_set_public_key(a, (uint8_t *)&point) != 1) { + if (sm2_key_set_public_key(a, &point) != 1) { error_print(); return -1; } @@ -532,7 +508,7 @@ int sm2_private_key_from_pem(SM2_KEY *a, FILE *fp) const uint8_t *cp = buf; size_t len; - if (pem_read(fp, "EC PRIVATE KEY", buf, &len) != 1) { + if (pem_read(fp, "EC PRIVATE KEY", buf, &len, sizeof(buf)) != 1) { error_print(); return -1; } @@ -567,7 +543,7 @@ int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp) const uint8_t *cp = buf; size_t len; - if (pem_read(fp, "PUBLIC KEY", buf, &len) != 1) { + if (pem_read(fp, "PUBLIC KEY", buf, &len, sizeof(buf)) != 1) { error_print(); return -1; } @@ -578,6 +554,10 @@ int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp) return 1; } +int sm2_public_key_copy(SM2_KEY *sm2_key, const SM2_KEY *pub_key) +{ + return sm2_key_set_public_key(sm2_key, &pub_key->public_key); +} int sm2_public_key_digest(const SM2_KEY *sm2_key, uint8_t dgst[32]) { diff --git a/src/sm2_lib.c b/src/sm2_lib.c index 10852c15..4e3bf406 100644 --- a/src/sm2_lib.c +++ b/src/sm2_lib.c @@ -104,7 +104,7 @@ int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *der, s //FIXME: 由于每次加密的时候密文编码长度不同,因此这个函数应该避免在out == NULL时输出一个长度! int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - size_t clen = SM2_CIPHERTEXT_SIZE(inlen); + size_t clen = sizeof(SM2_CIPHERTEXT)-1+inlen; // FIXME: not supported in MS VS size_t cbuf[clen]; SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)cbuf; @@ -127,7 +127,7 @@ int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *ou extern void sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks); -int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id) +int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id, size_t idlen) { uint8_t zin[] = { 0x00, 0x80, @@ -190,15 +190,13 @@ int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id) } else { SM3_CTX ctx; uint8_t idbits[2]; - size_t len; - len = strlen(id); - idbits[0] = (uint8_t)(len >> 5); - idbits[1] = (uint8_t)(len << 3); + idbits[0] = (uint8_t)(idlen >> 5); + idbits[1] = (uint8_t)(idlen << 3); sm3_init(&ctx); sm3_update(&ctx, idbits, 2); - sm3_update(&ctx, (uint8_t *)id, len); + sm3_update(&ctx, (uint8_t *)id, idlen); sm3_update(&ctx, zin + 18, 128); sm3_update(&ctx, pub->x, 32); sm3_update(&ctx, pub->y, 32); @@ -208,13 +206,13 @@ int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id) return 1; } -int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id) +int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen) { uint8_t z[32]; - if (!ctx || !key || !id || strlen(id) > SM2_MAX_ID_SIZE) { + if (!ctx || !key || !id || idlen > SM2_MAX_ID_SIZE) { return -1; } - sm2_compute_z(z, &key->public_key, id); + sm2_compute_z(z, &key->public_key, id, idlen); sm3_init(&ctx->sm3_ctx); sm3_update(&ctx->sm3_ctx, z, 32); @@ -241,13 +239,13 @@ int sm2_sign_resume(SM2_SIGN_CTX *ctx) return 0; } -int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id) +int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen) { uint8_t z[32]; - if (!ctx || !key || !id || strlen(id) > SM2_MAX_ID_SIZE) { + if (!ctx || !key || !id || idlen > SM2_MAX_ID_SIZE) { return -1; } - sm2_compute_z(z, &key->public_key, id); + sm2_compute_z(z, &key->public_key, id, idlen); sm3_init(&ctx->sm3_ctx); sm3_update(&ctx->sm3_ctx, z, 32); memcpy(&ctx->key, key, sizeof(SM2_KEY)); @@ -269,15 +267,14 @@ int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen) return ret; } -int sm2_set_private_key(SM2_KEY *key, const uint8_t private_key[32]) +int sm2_key_set_private_key(SM2_KEY *key, const uint8_t private_key[32]) { memcpy(&key->private_key, private_key, 32); return 1; } -// FIXME: 检查公钥是否正确 -int sm2_set_public_key(SM2_KEY *key, const uint8_t public_key[64]) +int sm2_key_set_public_key(SM2_KEY *key, const SM2_POINT *public_key) { - memcpy(&key->public_key, public_key, 64); + key->public_key = *public_key; return 1; } diff --git a/src/sm2_prn.c b/src/sm2_prn.c index c605c441..66a5d1b6 100644 --- a/src/sm2_prn.c +++ b/src/sm2_prn.c @@ -51,67 +51,57 @@ #include #include #include +#include #include // FIXME: 缺乏打印公钥的函数,有时候SM2_KEY中只有公钥,没有私钥 -int sm2_key_print(FILE *fp, const SM2_KEY *key, int format, int indent) +int sm2_key_print(FILE *fp, int format, int indent, const char *label, const SM2_KEY *key) { format_print(fp, format, indent, "SM2PrivateKey\n"); indent += 4; format_bytes(fp, format, indent, "private_key : ", key->private_key, 32); - format_print(fp, format, indent, "public_key:\n"); - sm2_point_print(fp, &key->public_key, format, indent + 4); + sm2_point_print(fp, format, indent + 4, "public_key", &key->public_key); return 1; } -int sm2_point_print(FILE *fp, const SM2_POINT *P, int format, int indent) +int sm2_point_print(FILE *fp, int format, int indent, const char *label, const SM2_POINT *P) { format_bytes(fp, format, indent, "x : ", P->x, 32); format_bytes(fp, format, indent, "y : ", P->y, 32); return 1; } -int sm2_print_signature(FILE *fp, const uint8_t *der, size_t derlen, int format, int indent) +int sm2_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) { - uint8_t buf[sizeof(SM2_SIGNATURE)] = {0}; - SM2_SIGNATURE *sig = (SM2_SIGNATURE *)buf; - const uint8_t *p = der; - int i; - - if (sm2_signature_from_der(sig, &p, &derlen) < 0) { - fprintf(stderr, "error: %s %d: invalid signature DER encoding\n", __FILE__, __LINE__); + SM2_SIGNATURE sig; + if (sm2_signature_from_der(&sig, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; } - if (derlen > 0) { - fprintf(stderr, "error: %s %d: %zu extra bytes at the end of DER\n", __FILE__, __LINE__, derlen); - } - - format_bytes(fp, format, indent, "r : ", sig->r, 32); - format_bytes(fp, format, indent, "s : ", sig->s, 32); + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + format_bytes(fp, fmt, ind, "r : ", sig.r, 32); + format_bytes(fp, fmt, ind, "s : ", sig.s, 32); return 1; } -int sm2_print_ciphertext(FILE *fp, const uint8_t *der, size_t derlen, int format, int indent) +int sm2_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) { - uint8_t buf[512 /* derlen */] = {0}; //FIXME: add -std=c99 to CMakeList.txt + uint8_t buf[512] = {0}; SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)buf; - const uint8_t *p = der; int i; - if (sm2_ciphertext_from_der(c, &p, &derlen) < 0) { - fprintf(stderr, "error: %s %d: invalid ciphertext DER encoding\n", __FILE__, __LINE__); + if (sm2_ciphertext_from_der(c, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; } - if (derlen > 0) { - fprintf(stderr, "error: %s %d: %zu extra bytes at the end of DER\n", __FILE__, __LINE__, derlen); - } - sm2_ciphertext_print(fp, c, format, indent); - return 1; -} - -int sm2_ciphertext_print(FILE *fp, const SM2_CIPHERTEXT *c, int format, int indent) -{ - format_bytes(fp, format, indent, "x", c->point.x, 32); - format_bytes(fp, format, indent, "y", c->point.y, 32); - format_bytes(fp, format, indent, "hash", c->hash, 32); - format_bytes(fp, format, indent, "ciphertext", c->ciphertext, c->ciphertext_size); + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + format_bytes(fp, fmt, ind, "XCoordinate", c->point.x, 32); + format_bytes(fp, fmt, ind, "YCoordinate", c->point.y, 32); + format_bytes(fp, fmt, ind, "HASH", c->hash, 32); + format_bytes(fp, fmt, ind, "CipherText", c->ciphertext, c->ciphertext_size); return 1; } diff --git a/src/sm4_modes.c b/src/sm4_modes.c index ce37d258..bfa17610 100644 --- a/src/sm4_modes.c +++ b/src/sm4_modes.c @@ -156,7 +156,7 @@ void sm4_ctr_encrypt(const SM4_KEY *key, uint8_t ctr[16], const uint8_t *in, siz int sm4_gcm_encrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, - uint8_t *out, const size_t taglen, uint8_t *tag) + uint8_t *out, size_t taglen, uint8_t *tag) { const uint8_t *pin = in; uint8_t *pout = out; diff --git a/src/sm9_math.c b/src/sm9_math.c index 8cd0390b..fd74355f 100644 --- a/src/sm9_math.c +++ b/src/sm9_math.c @@ -142,7 +142,8 @@ static void bn_from_bytes(bn_t r, const uint8_t in[32]) static int bn_from_hex(bn_t r, const char hex[65]) { uint8_t buf[32]; - if (hex2bin(hex, 64, buf) < 0) { + size_t len; + if (hex_to_bytes(hex, 64, buf, &len) < 0) { return -1; } bn_from_bytes(r, buf); diff --git a/src/version.c b/src/version.c index a7e97cc0..4d85939b 100644 --- a/src/version.c +++ b/src/version.c @@ -47,11 +47,14 @@ */ -#include -#include -#include "endian.h" +#include + +int gmssl_version_num(void) +{ + return GMSSL_VERSION_NUM; +} const char *gmssl_version(void) { - return "GmSSL 3.0 alpha"; + return GMSSL_VERSION_STR; } diff --git a/src/x509_alg.c b/src/x509_alg.c new file mode 100644 index 00000000..85d3c7e6 --- /dev/null +++ b/src/x509_alg.c @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + + +#define oid_x9_62 1,2,840,10045 + + +static uint32_t oid_sm3[] = { 1,2,156,10197,1,401 }; +static uint32_t oid_md5[] = { 1,2,840,113549,2,5 }; +static uint32_t oid_sha1[] = { 1,3,14,3,2,26 }; +static uint32_t oid_sha256[] = { 2,16,840,1,101,3,4,2,1 }; +static uint32_t oid_sha384[] = { 2,16,840,1,101,3,4,2,2 }; +static uint32_t oid_sha512[] = { 2,16,840,1,101,3,4,2,3 }; +static uint32_t oid_sha224[] = { 2,16,840,1,101,3,4,2,4 }; + +static const ASN1_OID_INFO x509_digest_algors[] = { + { OID_sm3, "sm3", oid_sm3, sizeof(oid_sm3)/sizeof(int) }, + { OID_md5, "md5", oid_md5, sizeof(oid_md5)/sizeof(int) }, + { OID_sha1, "sha1", oid_sha1, sizeof(oid_sha1)/sizeof(int) }, + { OID_sha224, "sha224", oid_sha224, sizeof(oid_sha224)/sizeof(int) }, + { OID_sha256, "sha256", oid_sha256, sizeof(oid_sha256)/sizeof(int) }, + { OID_sha384, "sha384", oid_sha384, sizeof(oid_sha384)/sizeof(int) }, + { OID_sha512, "sha512", oid_sha512, sizeof(oid_sha512)/sizeof(int) }, +}; + +static const int x509_digest_algors_count = + sizeof(x509_digest_algors)/sizeof(x509_digest_algors[0]); + +const char *x509_digest_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_digest_algors, x509_digest_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_digest_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_digest_algors, x509_digest_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_digest_algor_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_digest_algors, x509_digest_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_digest_algor_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = 0; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if ((ret = asn1_oid_info_from_der(&info, x509_digest_algors, x509_digest_algors_count, &p, &len)) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return ret; + } + *oid = info->oid; + return 1; +} + +int x509_digest_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_digest_algors, x509_digest_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static uint32_t oid_sm4_cbc[] = { 1,2,156,10197,1,104,2 }; +static uint32_t oid_aes128_cbc[] = { 2,16,840,1,101,3,4,1,2 }; +static uint32_t oid_aes192_cbc[] = { 2,16,840,1,101,3,4,1,22 }; +static uint32_t oid_aes256_cbc[] = { 2,16,840,1,101,3,4,1,42 }; + +static const ASN1_OID_INFO x509_enc_algors[] = { + { OID_sm4_cbc, "sm4-cbc", oid_sm4_cbc, sizeof(oid_sm4_cbc)/sizeof(int) }, + { OID_aes128_cbc, "aes128-cbc", oid_aes128_cbc, sizeof(oid_aes128_cbc)/sizeof(int) }, + { OID_aes192_cbc, "aes192-cbc", oid_aes192_cbc, sizeof(oid_aes192_cbc)/sizeof(int) }, + { OID_aes256_cbc, "aes256-cbc", oid_aes256_cbc, sizeof(oid_aes256_cbc)/sizeof(int) }, +}; + +static const int x509_enc_algors_count = + sizeof(x509_enc_algors)/sizeof(x509_enc_algors[0]); + +const char *x509_encryption_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_enc_algors, x509_enc_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_encryption_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_enc_algors, x509_enc_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_encryption_algor_to_der(int oid, const uint8_t *iv, size_t ivlen, + uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + + if (!(info = asn1_oid_info_from_oid(x509_enc_algors, x509_enc_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_octet_string_to_der(iv, ivlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1 + || asn1_octet_string_to_der(iv, ivlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_encryption_algor_from_der(int *oid, const uint8_t **iv, size_t *ivlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = OID_undef; + *iv = NULL; + *ivlen = 0; + + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_oid_info_from_der(&info, x509_enc_algors, x509_enc_algors_count, &p, &len) != 1 + || asn1_octet_string_from_der(iv, ivlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (!(*iv) || *ivlen != 16) { + error_print(); + return -1; + } + *oid = info->oid; + return 1; +} + +int x509_encryption_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + const uint8_t *iv; + size_t ivlen; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_enc_algors, x509_enc_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if (asn1_octet_string_from_der(&iv, &ivlen, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "iv: ", iv, ivlen); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static uint32_t oid_sm2sign_with_sm3[] = { 1,2,156,10197,1,501 }; +static uint32_t oid_rsasign_with_sm3[] = { 1,2,156,10197,1,504 }; +static uint32_t oid_ecdsa_with_sha1[] = { 1,2,840,10045,4,1 }; +static uint32_t oid_ecdsa_with_sha224[] = { 1,2,840,10045,4,3,1 }; +static uint32_t oid_ecdsa_with_sha256[] = { 1,2,840,10045,4,3,2 }; +static uint32_t oid_ecdsa_with_sha384[] = { 1,2,840,10045,4,3,3 }; +static uint32_t oid_ecdsa_with_sha512[] = { 1,2,840,10045,4,3,4 }; +static uint32_t oid_rsasign_with_sha1[] = { 1,2,840,113549,1,1,5 }; +static uint32_t oid_rsasign_with_sha224[] = { 1,2,840,113549,1,1,14 }; +static uint32_t oid_rsasign_with_sha256[] = { 1,2,840,113549,1,1,11 }; +static uint32_t oid_rsasign_with_sha384[] = { 1,2,840,113549,1,1,12 }; +static uint32_t oid_rsasign_with_sha512[] = { 1,2,840,113549,1,1,13 }; + +#define X509_ALGOR_OPT_NULL_PARAM 1 + +static const ASN1_OID_INFO x509_sign_algors[] = { + { OID_sm2sign_with_sm3, "sm2sign-with-sm3", oid_sm2sign_with_sm3, sizeof(oid_sm2sign_with_sm3)/sizeof(int), 0 }, + { OID_rsasign_with_sm3, "rsasign-with-sm3", oid_rsasign_with_sm3, sizeof(oid_rsasign_with_sm3)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM }, + { OID_ecdsa_with_sha1, "ecdsa-with-sha1", oid_ecdsa_with_sha1, sizeof(oid_ecdsa_with_sha1)/sizeof(int), 0 }, + { OID_ecdsa_with_sha224, "ecdsa-with-sha224", oid_ecdsa_with_sha224, sizeof(oid_ecdsa_with_sha224)/sizeof(int), 0} , + { OID_ecdsa_with_sha256, "ecdsa-with-sha256", oid_ecdsa_with_sha256, sizeof(oid_ecdsa_with_sha256)/sizeof(int), 0}, + { OID_ecdsa_with_sha384, "ecdsa-with-sha384", oid_ecdsa_with_sha384, sizeof(oid_ecdsa_with_sha384)/sizeof(int), 0 }, + { OID_ecdsa_with_sha512, "ecdsa-with-sha512", oid_ecdsa_with_sha512, sizeof(oid_ecdsa_with_sha512)/sizeof(int), 0 }, + { OID_rsasign_with_sha1, "sha1WithRSAEncryption", oid_rsasign_with_sha1, sizeof(oid_rsasign_with_sha1)/sizeof(int), 0 }, + { OID_rsasign_with_sha224, "sha224WithRSAEncryption", oid_rsasign_with_sha224, sizeof(oid_rsasign_with_sha224)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM }, + { OID_rsasign_with_sha256, "sha256WithRSAEncryption", oid_rsasign_with_sha256, sizeof(oid_rsasign_with_sha256)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM }, + { OID_rsasign_with_sha384, "sha384WithRSAEncryption", oid_rsasign_with_sha384, sizeof(oid_rsasign_with_sha384)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM }, + { OID_rsasign_with_sha512, "sha512WithRSAEncryption", oid_rsasign_with_sha512, sizeof(oid_rsasign_with_sha512)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM }, +}; + +static const int x509_sign_algors_count = + sizeof(x509_sign_algors)/sizeof(x509_sign_algors[0]); + +const char *x509_signature_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_sign_algors, x509_sign_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_signature_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_sign_algors, x509_sign_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_signature_algor_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_sign_algors, x509_sign_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || (info->flags && asn1_null_to_der(NULL, &len) != 1) + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1 + || (info->flags && asn1_null_to_der(out, outlen) != 1)) { + error_print(); + return -1; + } + return 1; +} + +int x509_signature_algor_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + int has_null_obj; + int i; + + *oid = OID_undef; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_oid_info_from_der(&info, x509_sign_algors, x509_sign_algors_count, &p, &len) != 1 + || (info->flags && asn1_null_from_der(&p, &len) < 0) + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + *oid = info->oid; + return 1; +} + +int x509_signature_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + int null_param; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_sign_algors, x509_sign_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if ((null_param = asn1_null_from_der(&d, &dlen)) < 0) goto err; + if (null_param) format_print(fp, fmt, ind, "parameters: %s\n", asn1_tag_name(ASN1_TAG_NULL)); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +/* +sm2encrypt: no parameters + +rsaes_oaep: from rfc 3560 +RSAES-OAEP-params ::= SEQUENCE { + hashFunc [0] AlgorithmIdentifier DEFAULT sha1Identifier, + maskGenFunc [1] AlgorithmIdentifier DEFAULT mgf1SHA1Identifier, + pSourceFunc [2] AlgorithmIdentifier DEFAULT +*/ + +static uint32_t oid_sm2encrypt[] = { 1,2,156,10197,1,301,2 }; +static uint32_t oid_rsa_encryption[] = { 1,2,840,113549,1,1,1 }; +static uint32_t oid_rsaes_oaep[] = { 1,2,840,113549,1,1,7 }; + +static const ASN1_OID_INFO x509_pke_algors[] = { + { OID_sm2encrypt, "sm2encrypt", oid_sm2encrypt, sizeof(oid_sm2encrypt)/sizeof(int) }, + { OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int) }, + { OID_rsaes_oaep, "rsaesOAEP", oid_rsaes_oaep, sizeof(oid_rsaes_oaep)/sizeof(int) }, +}; + +static const int x509_pke_algors_count = + sizeof(x509_pke_algors)/sizeof(x509_pke_algors[0]); + +const char *x509_public_key_encryption_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_pke_algors, x509_pke_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_public_key_encryption_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_pke_algors, x509_pke_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_public_key_encryption_algor_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + + if (oid != OID_sm2encrypt) { + error_print(); + return -1; + } + if (!(info = asn1_oid_info_from_oid(x509_pke_algors, x509_pke_algors_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_public_key_encryption_algor_from_der(int *oid, const uint8_t **params, size_t *params_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = OID_undef; + *params = NULL; + *params_len = 0; + + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_oid_info_from_der(&info, x509_pke_algors, x509_pke_algors_count, &p, &len) != 1) { + error_print(); + return -1; + } + *oid = info->oid; + if (asn1_length_is_zero(len) != 1) { + if (info->oid == OID_sm2encrypt) { + error_print(); + return -1; + } + *params = p; + *params_len = len; + } + return 1; +} + +int x509_public_key_encryption_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_pke_algors, x509_pke_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->name); + if (asn1_length_is_zero(dlen) != 1) { + if (info->oid == OID_sm2encrypt) goto err; + format_bytes(fp, fmt, ind, "parameters: ", d, dlen); + } + return 1; +err: + error_print(); + return -1; +} + + +#define oid_sm_scheme 1,2,156,10197,1 +static uint32_t oid_sm2[] = { oid_sm_scheme,301 }; + +#define oid_x9_62_curves oid_x9_62,3 +#define oid_x9_62_prime_curves oid_x9_62_curves,1 +static uint32_t oid_prime192v1[] = { oid_x9_62_prime_curves,1 }; +static uint32_t oid_prime256v1[] = { oid_x9_62_prime_curves,7 }; // NIST P-256 + +#define oid_secg_curve 1,3,132,0 +static uint32_t oid_secp256k1[] = { oid_secg_curve,10 }; +static uint32_t oid_secp384r1[] = { oid_secg_curve,34 }; // NIST P-384 +static uint32_t oid_secp521r1[] = { oid_secg_curve,35 }; // NIST P-521 + + +static const ASN1_OID_INFO ec_curves[] = { + { OID_sm2, "sm2", oid_sm2, sizeof(oid_sm2)/sizeof(int), 0, "SM2" }, + { OID_prime192v1, "prime192v1", oid_prime192v1, sizeof(oid_prime192v1)/sizeof(int), 0, }, + { OID_prime256v1, "prime256v1", oid_prime256v1, sizeof(oid_prime256v1)/sizeof(int), 0, "NIST P-256" }, + { OID_secp256k1, "secp256k1", oid_secp256k1, sizeof(oid_secp256k1)/sizeof(int) }, + { OID_secp384r1, "secp384r1", oid_secp384r1, sizeof(oid_secp384r1)/sizeof(int), 0, "NIST P-384" }, + { OID_secp521r1, "secp521r1", oid_secp521r1, sizeof(oid_secp521r1)/sizeof(int), 0, "NIST P-521" } +}; + +static const int ec_curves_count = sizeof(ec_curves)/sizeof(ec_curves[0]); + +const char *ec_curve_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(ec_curves, ec_curves_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int ec_curve_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(ec_curves, ec_curves_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + + +static uint32_t oid_ec_public_key[] = { oid_x9_62,2,1 }; +//static uint32_t oid_rsa_encryption[] = { 1,2,840,113549,1,1,1 }; + +static const ASN1_OID_INFO x509_public_key_algors[] = { + { OID_ec_public_key, "ecPublicKey", oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), 0, "X9.62 ecPublicKey" }, + { OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), 0, "RSAEncryption" }, +}; + +static const int x509_public_key_algors_count = + sizeof(x509_public_key_algors)/sizeof(x509_public_key_algors[0]); + +const char *x509_public_key_algor_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_public_key_algors, x509_public_key_algors_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_public_key_algor_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_public_key_algors, x509_public_key_algors_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_ec_public_key_algor_to_der(int curve_oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + + if (!(info = asn1_oid_info_from_oid(ec_curves, ec_curves_count, curve_oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), NULL, &len) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_ec_public_key_algor_from_der(int *curve_oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *curve_oid = OID_undef; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_oid_info_from_der(&info, x509_public_key_algors, x509_public_key_algors_count, &p, &len) != 1) { + error_print(); + return -1; + } + if (info->oid != OID_ec_public_key) { + error_print(); + return -1; + } + if (asn1_oid_info_from_der(&info, ec_curves, ec_curves_count, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + *curve_oid = info->oid; + return 1; +} + +int x509_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const ASN1_OID_INFO *info; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_oid_info_from_der(&info, x509_public_key_algors, x509_public_key_algors_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "algorithm: %s\n", info->description); + if (info->oid != OID_ec_public_key) goto err; + if (asn1_oid_info_from_der(&info, ec_curves, ec_curves_count, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "namedCurve: %s\n", info->name); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} diff --git a/src/x509_algor.c b/src/x509_algor.c deleted file mode 100644 index 7dd41c53..00000000 --- a/src/x509_algor.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the GmSSL Project. - * (http://gmssl.org/)" - * - * 4. The name "GmSSL Project" must not be used to endorse or promote - * products derived from this software without prior written - * permission. For written permission, please contact - * guanzhi1980@gmail.com. - * - * 5. Products derived from this software may not be called "GmSSL" - * nor may "GmSSL" appear in their names without prior written - * permission of the GmSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the GmSSL Project - * (http://gmssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - - -typedef struct { - int algor; - char *name; - const uint32_t *nodes; - size_t nodes_count; - int has_params; -} X509_ALGOR_INFO; - - -static const uint32_t oid_sm3[] = {1, 2, 156, 10197, 1, 401}; -static const uint32_t oid_md5[] = {1, 2, 840, 113549, 2, 5}; -static const uint32_t oid_sha1[] = {1, 3, 14, 3, 2, 26}; -static const uint32_t oid_sha256[] = {2, 16, 840, 1, 101, 3, 4, 2, 1}; -static const uint32_t oid_sha384[] = {2, 16, 840, 1, 101, 3, 4, 2, 2}; -static const uint32_t oid_sha512[] = {2, 16, 840, 1, 101, 3, 4, 2, 3}; -static const uint32_t oid_sha224[] = {2, 16, 840, 1, 101, 3, 4, 2, 4}; - -static X509_ALGOR_INFO x509_digest_algors[] = { - { OID_sm3, "sm3", oid_sm3, sizeof(oid_sm3)/sizeof(int), 0 }, - { OID_md5, "md5", oid_md5, sizeof(oid_md5)/sizeof(int), 0 }, - { OID_sha1, "sha1", oid_sha1, sizeof(oid_sha1)/sizeof(int), 0 }, - { OID_sha224, "sha224", oid_sha224, sizeof(oid_sha224)/sizeof(int), 0 }, - { OID_sha256, "sha256", oid_sha256, sizeof(oid_sha256)/sizeof(int), 0 }, - { OID_sha384, "sha384", oid_sha384, sizeof(oid_sha384)/sizeof(int), 0 }, - { OID_sha512, "sha512", oid_sha512, sizeof(oid_sha512)/sizeof(int), 0 }, -}; - -static const int x509_digest_algors_count = - sizeof(x509_digest_algors)/sizeof(x509_digest_algors[0]); - -const char *x509_digest_algor_name(int algor) -{ - int i; - for (i = 0; i < x509_digest_algors_count; i++) { - if (algor == x509_digest_algors[i].algor) { - return x509_digest_algors[i].name; - } - } - return NULL; -} - -int x509_digest_algor_from_name(const char *name) -{ - int i; - for (i = 0; i < x509_digest_algors_count; i++) { - if (strcmp(name, x509_digest_algors[i].name) == 0) { - return x509_digest_algors[i].algor; - } - } - return OID_undef; -} - -int x509_digest_algor_to_der(int algor, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - const uint32_t *nodes = NULL; - size_t nodes_count; - int i; - - for (i = 0; i < x509_digest_algors_count; i++) { - if (algor == x509_digest_algors[i].algor) { - nodes = x509_digest_algors[i].nodes; - nodes_count = x509_digest_algors[i].nodes_count; - break; - } - } - if (!nodes) { - error_print(); - return -1; - } - - if (asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_digest_algor_from_der(int *algor, uint32_t *nodes, size_t *nodes_count, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int i; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return -1; - } - if (asn1_object_identifier_from_der(NULL, nodes, nodes_count, &data, &datalen) != 1 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - - for (i = 0; i < x509_digest_algors_count; i++) { - if (*nodes_count == x509_digest_algors[i].nodes_count - && memcmp(nodes, x509_digest_algors[i].nodes, (*nodes_count) * sizeof(int)) == 0) { - *algor = x509_digest_algors[i].algor; - return 1; - } - } - *algor = OID_undef; - error_print(); - return -1; -} - - -static uint32_t oid_sm4_cbc[] = {1, 2, 156, 10197, 1, 104, 2}; -static uint32_t oid_aes128_cbc[] = {2, 16, 840, 1, 101, 3, 4, 1, 2}; -static uint32_t oid_aes192_cbc[] = {2, 16, 840, 1, 101, 3, 4, 1, 22}; -static uint32_t oid_aes256_cbc[] = {2, 16, 840, 1, 101, 3, 4, 1, 42}; - -static const X509_ALGOR_INFO x509_encryption_algors[] = { - { OID_sm4_cbc, "sm4-cbc", oid_sm4_cbc, sizeof(oid_sm4_cbc)/sizeof(int), 1 }, - { OID_aes128_cbc, "aes128-cbc", oid_aes128_cbc, sizeof(oid_aes128_cbc)/sizeof(int), 1 }, - { OID_aes192_cbc, "aes192-cbc", oid_aes192_cbc, sizeof(oid_aes192_cbc)/sizeof(int), 1 }, - { OID_aes256_cbc, "aes256-cbc", oid_aes256_cbc, sizeof(oid_aes256_cbc)/sizeof(int), 1 }, -}; - -static const int x509_encryption_algors_count = - sizeof(x509_encryption_algors)/sizeof(x509_encryption_algors[0]); - -const char *x509_encryption_algor_name(int algor) -{ - int i; - for (i = 0; i < x509_encryption_algors_count; i++) { - if (algor == x509_encryption_algors[i].algor) { - return x509_encryption_algors[i].name; - } - } - return NULL; -} - -int x509_encryption_algor_from_name(const char *name) -{ - int i; - for (i = 0; i < x509_encryption_algors_count; i++) { - if (strcmp(name, x509_encryption_algors[i].name) == 0) { - return x509_encryption_algors[i].algor; - } - } - return 0; -} - -int x509_encryption_algor_to_der(int algor, const uint8_t *iv, size_t ivlen, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - const uint32_t *nodes = NULL; - size_t nodes_count; - int i; - - for (i = 0; i < x509_encryption_algors_count; i++) { - if (algor == x509_encryption_algors[i].algor) { - nodes = x509_encryption_algors[i].nodes; - nodes_count = x509_encryption_algors[i].nodes_count; - break; - } - } - if (i >= x509_encryption_algors_count ) { - error_print(); - return -1; - } - - if (asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, NULL, &len) != 1 - || asn1_octet_string_to_der(iv, ivlen, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, out, outlen) != 1 - || asn1_octet_string_to_der(iv, ivlen, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_encryption_algor_from_der(int *algor, uint32_t *nodes, size_t *nodes_count, - const uint8_t **iv, size_t *ivlen, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int i; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_object_identifier_from_der(NULL, nodes, nodes_count, &data, &datalen) != 1 - || asn1_octet_string_from_der(iv, ivlen, &data, &datalen) != 1 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - if (!(*iv) || *ivlen != 16) { - error_print(); - return -1; - } - for (i = 0; i < x509_encryption_algors_count; i++) { - if (*nodes_count == x509_encryption_algors[i].nodes_count - && memcmp(nodes, x509_encryption_algors[i].nodes, (*nodes_count) * sizeof(int)) == 0) { - *algor = x509_encryption_algors[i].algor; - return 1; - } - } - - *algor = OID_undef; - error_print(); - return -1; -} - - -static uint32_t oid_sm2sign_with_sm3[] = {1, 2, 156, 10197, 1, 501}; -static uint32_t oid_rsasign_with_sm3[] = {1, 2, 156, 10197, 1, 504}; -static uint32_t oid_ecdsa_with_sha1[] = {1, 2, 840, 10045, 4, 1}; -static uint32_t oid_ecdsa_with_sha224[] = {1, 2, 840, 10045, 4, 3, 1}; -static uint32_t oid_ecdsa_with_sha256[] = {1, 2, 840, 10045, 4, 3, 2}; -static uint32_t oid_ecdsa_with_sha384[] = {1, 2, 840, 10045, 4, 3, 3}; -static uint32_t oid_ecdsa_with_sha512[] = {1, 2, 840, 10045, 4, 3, 4}; -static uint32_t oid_rsasign_with_sha1[] = {1, 2,840, 113549, 1, 1, 5}; -static uint32_t oid_rsasign_with_sha224[] = {1, 2, 840, 113549, 1, 1, 14}; -static uint32_t oid_rsasign_with_sha256[] = {1, 2, 840, 113549, 1, 1, 11}; -static uint32_t oid_rsasign_with_sha384[] = {1, 2, 840, 113549, 1, 1, 12}; -static uint32_t oid_rsasign_with_sha512[] = {1, 2, 840, 113549, 1, 1, 13}; - -static const X509_ALGOR_INFO x509_sign_algors[] = { - { OID_sm2sign_with_sm3, "sm2sign-with-sm3", oid_sm2sign_with_sm3, sizeof(oid_sm2sign_with_sm3)/sizeof(int), 0 }, - { OID_rsasign_with_sm3, "rsasign-with-sm3", oid_rsasign_with_sm3, sizeof(oid_rsasign_with_sm3)/sizeof(int), 1 }, - { OID_ecdsa_with_sha1, "ecdsa-with-sha1", oid_ecdsa_with_sha1, sizeof(oid_ecdsa_with_sha1)/sizeof(int), 0 }, - { OID_ecdsa_with_sha224, "ecdsa-with-sha224", oid_ecdsa_with_sha224, sizeof(oid_ecdsa_with_sha224)/sizeof(int), 0} , - { OID_ecdsa_with_sha256, "ecdsa-with-sha256", oid_ecdsa_with_sha256, sizeof(oid_ecdsa_with_sha256)/sizeof(int), 0}, - { OID_ecdsa_with_sha384, "ecdsa-with-sha384", oid_ecdsa_with_sha384, sizeof(oid_ecdsa_with_sha384)/sizeof(int), 0 }, - { OID_ecdsa_with_sha512, "ecdsa-with-sha512", oid_ecdsa_with_sha512, sizeof(oid_ecdsa_with_sha512)/sizeof(int), 0 }, - { OID_rsasign_with_sha1, "sha1WithRSAEncryption", oid_rsasign_with_sha1, sizeof(oid_rsasign_with_sha1)/sizeof(int), 0 }, - { OID_rsasign_with_sha224, "sha224WithRSAEncryption", oid_rsasign_with_sha224, sizeof(oid_rsasign_with_sha224)/sizeof(int), 1 }, - { OID_rsasign_with_sha256, "sha256WithRSAEncryption", oid_rsasign_with_sha256, sizeof(oid_rsasign_with_sha256)/sizeof(int), 1 }, - { OID_rsasign_with_sha384, "sha384WithRSAEncryption", oid_rsasign_with_sha384, sizeof(oid_rsasign_with_sha384)/sizeof(int), 1 }, - { OID_rsasign_with_sha512, "sha512WithRSAEncryption", oid_rsasign_with_sha512, sizeof(oid_rsasign_with_sha512)/sizeof(int), 1 }, -}; - -static const int x509_sign_algors_count = - sizeof(x509_sign_algors)/sizeof(x509_sign_algors[0]); - -const char *x509_signature_algor_name(int algor) -{ - int i; - for (i = 0; i < x509_sign_algors_count; i++) { - if (algor == x509_sign_algors[i].algor) { - return x509_sign_algors[i].name; - } - } - return NULL; -} - -int x509_signature_algor_from_name(const char *name) -{ - int i; - for (i = 0; i < x509_sign_algors_count; i++) { - if (strcmp(name, x509_sign_algors[i].name) == 0) { - return x509_sign_algors[i].algor; - } - } - return OID_undef; -} - -int x509_signature_algor_to_der(int algor, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - const uint32_t *nodes; - size_t nodes_count; - int has_null_obj; - int i; - - for (i = 0; i < x509_sign_algors_count; i++) { - if (algor == x509_sign_algors[i].algor) { - nodes = x509_sign_algors[i].nodes; - nodes_count = x509_sign_algors[i].nodes_count; - has_null_obj = x509_sign_algors[i].has_params; - break; - } - } - if (i >= x509_sign_algors_count) { - error_print(); - return -1; - } - - if (asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, NULL, &len) != 1 - || (has_null_obj && asn1_null_to_der(NULL, &len) != 1) - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, out, outlen) != 1 - || (has_null_obj && asn1_null_to_der(out, outlen) != 1)) { - error_print(); - return -1; - } - return 1; -} - -int x509_signature_algor_from_der(int *algor, uint32_t *nodes, size_t *nodes_count, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int has_null_obj; - int i; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - if (ret == 0) error_print(); - return ret; - } - if (asn1_object_identifier_from_der(algor, nodes, nodes_count, &data, &datalen) != 1) { - error_print(); - return -1; - } - for (i = 0; i < x509_sign_algors_count; i++) { - if (*nodes_count == x509_sign_algors[i].nodes_count - && memcmp(nodes, x509_sign_algors[i].nodes, (*nodes_count) * sizeof(int)) == 0) { - *algor = x509_sign_algors[i].algor; - has_null_obj = x509_sign_algors[i].has_params; - break; - } - } - if (i >= x509_sign_algors_count) { - error_print(); - return -1; - } - - if (has_null_obj && asn1_null_from_der(&data, &datalen) != 1) { - error_print(); - return -1; - } - if (datalen) { - error_print(); - return -1; - } - return 1; -} - -/* -from rfc 3560: -RSAES-OAEP-params ::= SEQUENCE { - hashFunc [0] AlgorithmIdentifier DEFAULT sha1Identifier, - maskGenFunc [1] AlgorithmIdentifier DEFAULT mgf1SHA1Identifier, - pSourceFunc [2] AlgorithmIdentifier DEFAULT - -SM2公钥加密算法参数默认为SM3,本实现在to_der时不编码参数 -在from_der时,将参数直接返回给应用,不做处理 -*/ - -static uint32_t oid_sm2encrypt[] = {1, 2, 156, 10197, 1, 301, 2}; -static uint32_t oid_rsa_encryption[] = {1, 2, 840, 113549, 1, 1, 1}; -static uint32_t oid_rsaes_oaep[] = {1, 2, 840, 113549, 1, 1, 7}; - -static const X509_ALGOR_INFO x509_pke_algors[] = { - { OID_sm2encrypt, "sm2encrypt", oid_sm2encrypt, sizeof(oid_sm2encrypt)/sizeof(int) }, - { OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int) }, - { OID_rsaes_oaep, "rsaesOAEP", oid_rsaes_oaep, sizeof(oid_rsaes_oaep)/sizeof(int) }, -}; - -static const int x509_pke_algors_count = - sizeof(x509_pke_algors)/sizeof(x509_pke_algors[0]); - -const char *x509_public_key_encryption_algor_name(int algor) -{ - int i; - for (i = 0; i < x509_pke_algors_count; i++) { - if (algor == x509_pke_algors[i].algor) { - return x509_pke_algors[i].name; - } - } - return NULL; -} - -int x509_public_key_encryption_algor_from_name(const char *name) -{ - int i; - for (i = 0; i < x509_pke_algors_count; i++) { - if (strcmp(name, x509_pke_algors[i].name) == 0) { - return x509_pke_algors[i].algor; - } - } - return OID_undef; -} - -int x509_public_key_encryption_algor_to_der(int algor, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - const uint32_t *nodes; - size_t nodes_count; - int i; - - for (i = 0; i < x509_pke_algors_count; i++) { - if (algor == x509_pke_algors[i].algor) { - nodes = x509_pke_algors[i].nodes; - nodes_count = x509_pke_algors[i].nodes_count; - break; - } - } - if (i >= x509_pke_algors_count) { - error_print(); - return -1; - } - - if (asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(OID_undef, nodes, nodes_count, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_public_key_encryption_algor_from_der(int *algor, uint32_t *nodes, size_t *nodes_count, - const uint8_t **params, size_t *params_len, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - int i; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_object_identifier_from_der(NULL, nodes, nodes_count, &data, &datalen) != 1) { - error_print(); - return -1; - } - - for (i = 0; i < x509_pke_algors_count; i++) { - if (*nodes_count == x509_pke_algors[i].nodes_count - && memcmp(nodes, x509_pke_algors[i].nodes, (*nodes_count) * sizeof(int)) == 0) { - *algor = x509_pke_algors[i].algor; - break; - } - } - if (i >= x509_pke_algors_count) { - error_print(); - return -1; - } - if (datalen) { - *params = data; - *params_len = datalen; - } - return 1; -} diff --git a/src/x509_asn1.c b/src/x509_asn1.c deleted file mode 100644 index 75624f88..00000000 --- a/src/x509_asn1.c +++ /dev/null @@ -1,1424 +0,0 @@ -/* - * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the GmSSL Project. - * (http://gmssl.org/)" - * - * 4. The name "GmSSL Project" must not be used to endorse or promote - * products derived from this software without prior written - * permission. For written permission, please contact - * guanzhi1980@gmail.com. - * - * 5. Products derived from this software may not be called "GmSSL" - * nor may "GmSSL" appear in their names without prior written - * permission of the GmSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the GmSSL Project - * (http://gmssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -const char *x509_version_name(int version) -{ - switch (version) { - case X509_version_v1: return "v1"; - case X509_version_v2: return "v2"; - case X509_version_v3: return "v3"; - default: return ""; - } -} - -int x509_version_to_der(int version, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - switch (version) { - case X509_version_v1: - return 0; - case X509_version_v2: - case X509_version_v3: - break; - default: - error_print_msg("invalid version %d\n", version); - return -1; - } - if (asn1_int_to_der(version, NULL, &len) != 1 - || asn1_explicit_header_to_der(0, len, out, outlen) != 1 - || asn1_int_to_der(version, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_version_from_der(int *version, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_explicit_from_der(0, &data, &datalen, in, inlen)) < 0) { - error_print(); - return -1; - } else if (ret == 0) { - *version = X509_version_v1; - return 1; - } - - if (asn1_int_from_der(version, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - switch (*version) { - case X509_version_v1: - error_puts("warning: version v1 should not be encoded"); - break; - case X509_version_v2: - case X509_version_v3: - break; - default: - error_print(); - return -1; - } - return 1; -} - - -/* - from RFC 5280 section 4.1.2.5 - - CAs conforming to this profile MUST always encode certificate - validity dates through the year 2049 as UTCTime; certificate validity - dates in 2050 or later MUST be encoded as GeneralizedTime. - Conforming applications MUST be able to process validity dates that - are encoded in either UTCTime or GeneralizedTime. - - To indicate that a certificate has no well-defined expiration date, - the notAfter SHOULD be assigned the GeneralizedTime value of - 99991231235959Z. -*/ - -int x509_validity_set_days(X509_VALIDITY *a, time_t not_before, int days) -{ - struct tm tm_val; - if (!a || not_before < 0 || days < 1 || days > 3650) { - return 0; - } - a->not_before = not_before; - gmtime_r(¬_before, &tm_val); - tm_val.tm_mday += days; - a->not_after = mktime(&tm_val); - - return 1; -} - -int x509_time_to_der(time_t a, uint8_t **out, size_t *outlen) -{ - int ret; - struct tm tm_val; - - gmtime_r(&a, &tm_val); - if (tm_val.tm_year < 2050 - 1900) { - ret = asn1_utc_time_to_der(a, out, outlen); - } else { - ret = asn1_generalized_time_to_der(a, out, outlen); - } - - if (ret != 1) { - error_print(); - } - return ret; -} - -int x509_time_from_der(time_t *a, const uint8_t **in, size_t *inlen) -{ - int ret; - if (!a || !in || !(*in) || !inlen) { - error_print(); - return -1; - } - if ((ret = asn1_utc_time_from_der(a, in, inlen)) == 0) { - ret = asn1_generalized_time_from_der(a, in, inlen); - } - return ret; -} - -int x509_validity_to_der(const X509_VALIDITY *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (x509_time_to_der(a->not_before, NULL, &len) != 1 - || x509_time_to_der(a->not_after, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_time_to_der(a->not_before, out, outlen) != 1 - || x509_time_to_der(a->not_after, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_validity_from_der(X509_VALIDITY *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if (!a || !in || !(*in) || !inlen) { - error_print(); - return -1; - } - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_time_from_der(&a->not_before, &data, &datalen) != 1 - || x509_time_from_der(&a->not_after, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - if (a->not_before >= a->not_after) { - error_print(); - return -1; - } - return 1; -} - -int x509_validity_print(FILE *fp, const X509_VALIDITY *validity, int format, int indent) -{ - format_print(fp, format, indent, "NotBefore : %s", ctime(&validity->not_before)); - format_print(fp, format, indent, "NotAfter : %s", ctime(&validity->not_after)); - return 1; -} - - - -int x509_directory_string_to_der(int tag, const char *a, size_t alen, uint8_t **out, size_t *outlen) -{ - int ret = 0; - - switch (tag) { - case ASN1_TAG_TeletexString: - case ASN1_TAG_PrintableString: - case ASN1_TAG_UniversalString: - case ASN1_TAG_UTF8String: - if (strlen(a) != alen) { - error_print(); - return -1; - } - } - - switch (tag) { - case ASN1_TAG_PrintableString: - ret = asn1_printable_string_to_der(a, out, outlen); - break; - case ASN1_TAG_UTF8String: - ret = asn1_utf8_string_to_der(a, out, outlen); - break; - case ASN1_TAG_TeletexString: - case ASN1_TAG_UniversalString: - case ASN1_TAG_BMPString: - error_print(); - return -1; - default: - error_print(); - return -1; - } - - if (ret < 0) { - error_print(); - return -1; - } - return ret; -} - - -int x509_directory_string_from_der(int *tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen) -{ - int ret; - - if ((ret = asn1_any_type_from_der(tag, (const uint8_t **)a, alen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - switch (*tag) { - case ASN1_TAG_PrintableString: - case ASN1_TAG_UTF8String: - case ASN1_TAG_TeletexString: - case ASN1_TAG_UniversalString: - // FIXME: check no zero in string - break; - case ASN1_TAG_BMPString: - break; - default: - error_print(); - return -1; - } - return 1; -} - -static const struct { - int oid; - int is_printable_string_only; - int minlen; - int maxlen; -} x509_rdns[] = { - { OID_at_countryName, 1, 2, 2 }, - { OID_at_stateOrProvinceName, 0, 1, X509_ub_state_name }, - { OID_at_localityName, 0, 1, X509_ub_locality_name }, - { OID_at_organizationName, 0, 1, X509_ub_state_name }, - { OID_at_organizationalUnitName, 0, 1, X509_ub_organizational_unit_name }, - { OID_at_organizationName, 0, 1, X509_ub_organization_name }, - { OID_at_commonName, 0, 1, X509_ub_common_name }, - { OID_at_serialNumber, 1, 1, X509_ub_serial_number }, - { OID_at_dnQualifier, 1, 1, 64 }, // max length unspecified in RFC 5280 - { OID_at_title, 0, 1, X509_ub_title }, - { OID_at_surname, 0, 1, X509_ub_name }, - { OID_at_givenName, 0, 1, X509_ub_name }, - { OID_at_initials, 0, 1, X509_ub_name }, - { OID_at_generationQualifier, 0, 1, X509_ub_name }, - { OID_at_pseudonym, 0, 1, X509_ub_pseudonym }, -}; - -static int x509_rdn_check(int oid, int tag, const char *str, int len) -{ - int i; - for (i = 0; i < sizeof(x509_rdns)/sizeof(x509_rdns[0]); i++) { - if (oid == x509_rdns[i].oid) { - switch (tag) { - case ASN1_TAG_PrintableString: - case ASN1_TAG_UTF8String: - case ASN1_TAG_TeletexString: - case ASN1_TAG_UniversalString: - case ASN1_TAG_BMPString: - break; - default: - error_print(); - return -1; - } - if (x509_rdns[i].is_printable_string_only && tag != ASN1_TAG_PrintableString) { - error_print(); - return -1; - } - if (len < x509_rdns[i].minlen || len > x509_rdns[i].maxlen) { - error_print(); - return -1; - } - } - } - return 1; -} - - -int x509_name_add_rdn_ex(X509_NAME *a, int oid, int tag, const char *str, size_t len) -{ - int i; - - if (a->count >= 8) { - return -1; - } - for (i = 0; i < a->count; i++) { - if (oid == a->oids[i]) { - error_print(); - return -1; - } - } - - if (x509_rdn_check(oid, tag, str, len) != 1) { - error_print(); - return -1; - } - - switch (oid) { - case OID_at_countryName: - memcpy(a->country, str, len); - break; - case OID_at_stateOrProvinceName: - memcpy(a->state_or_province, str, len); - break; - case OID_at_localityName: - memcpy(a->locality, str, len); - break; - case OID_at_organizationName: - memcpy(a->org, str, len); - break; - case OID_at_organizationalUnitName: - memcpy(a->org_unit, str, len); - break; - case OID_at_commonName: - memcpy(a->common_name, str, len); - break; - case OID_at_serialNumber: - memcpy(a->serial_number, str, len); - break; - case OID_at_dnQualifier: - memcpy(a->dn_qualifier, str, len); - break; - default: - error_print(); - return -1; - } - - a->oids[a->count] = oid; - a->tags[a->count] = tag; - a->count++; - - return 1; -} - -// 这个函数可能是有问题的,因为RDN可能是bmp string,因此这里应该给一个长度 -int x509_rdn_to_der(int oid, int tag, const char *str, uint8_t **out, size_t *outlen) -{ - size_t len = 0, seqlen = 0; - - if (asn1_object_identifier_to_der(oid, NULL, 0, NULL, &len) != 1 - || x509_directory_string_to_der(tag, str, strlen(str), NULL, &len) != 1 - || asn1_sequence_header_to_der(len, NULL, &seqlen) != 1) { - error_print(); - return -1; - } - seqlen += len; - if (asn1_set_header_to_der(seqlen, out, outlen) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(oid, NULL, 0, out, outlen) != 1 - || x509_directory_string_to_der(tag, str, strlen(str), out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_rdn_from_der(int *oid, int *tag, const char **str, size_t *slen, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *seq, *data; - size_t seqlen = 0, datalen = 0; - uint32_t nodes[32]; - size_t nodes_count; - - if ((ret = asn1_set_from_der(&seq, &seqlen, in, inlen)) != 1) { - error_print(); - return ret; - } - if (asn1_sequence_from_der(&data, &datalen, &seq, &seqlen) != 1 - || seqlen > 0) { - error_print(); - return -1; - } - - if (asn1_object_identifier_from_der(oid, nodes, &nodes_count, &data, &datalen) != 1) { - error_print(); - return -1; - } - if (x509_directory_string_from_der(tag, str, slen, &data, &datalen) != 1) { - error_print(); - return -1; - } - if (datalen > 0) { - error_print(); - return -1; - } - if (x509_rdn_check(*oid, *tag, *str, *slen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_name_from_der(X509_NAME *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - memset(a, 0, sizeof(X509_NAME)); - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) <= 0) { - error_print(); - return ret; - } - while (datalen) { - int oid, tag; - const char *str; - size_t len; - if (x509_rdn_from_der(&oid, &tag, &str, &len, &data, &datalen) != 1 - || x509_name_add_rdn_ex(a, oid, tag, str, len) != 1) { - error_print(); - return -1; - } - } - return 1; -} - -const char *x509_name_rdn(const X509_NAME *name, int oid) -{ - switch (oid) { - case OID_at_countryName: - return name->country; - case OID_at_stateOrProvinceName: - return name->state_or_province; - case OID_at_localityName: - return name->locality; - case OID_at_organizationName: - return name->org; - case OID_at_organizationalUnitName: - return name->org_unit; - case OID_at_commonName: - return name->common_name; - case OID_at_serialNumber: - return name->serial_number; - case OID_at_dnQualifier: - return name->dn_qualifier; - } - error_print(); - return NULL; -} - -int x509_name_print(FILE *fp, const X509_NAME *name, int format, int indent) -{ - int i; - for (i = 0; i < name->count; i++) { - format_print(fp, format, indent, "%s : %s\n", - asn1_object_identifier_name(name->oids[i]), - //asn1_tag_name(name->tags[i]), - x509_name_rdn(name, name->oids[i])); - } - return 1; -} - -int x509_name_equ(const X509_NAME *a, const X509_NAME *b) -{ - uint8_t abuf[256]; - uint8_t bbuf[256]; - uint8_t *ap = abuf; - uint8_t *bp = bbuf; - size_t alen = 0, blen = 0; - - x509_name_to_der(a, &ap, &alen); - x509_name_to_der(b, &bp, &blen); - if (alen == blen && memcmp(abuf, bbuf, alen) == 0) { - return 1; - } else return 0; -} - -int x509_name_to_der(const X509_NAME *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - int oid, tag, i; - - // 在前面的循环中把输出字符串的指针做赋值,这样不需要重复这个循环 - - for (i = 0; i < a->count; i++) { - oid = a->oids[i]; - tag = a->tags[i]; - - switch (oid) { - case OID_at_countryName: - x509_rdn_to_der(oid, tag, a->country, NULL, &len); - break; - case OID_at_stateOrProvinceName: - x509_rdn_to_der(oid, tag, a->state_or_province, NULL, &len); - break; - case OID_at_localityName: - x509_rdn_to_der(oid, tag, a->locality, NULL, &len); - break; - case OID_at_organizationName: - x509_rdn_to_der(oid, tag, a->org, NULL, &len); - break; - case OID_at_organizationalUnitName: - x509_rdn_to_der(oid, tag, a->org_unit, NULL, &len); - break; - case OID_at_commonName: - x509_rdn_to_der(oid, tag, a->common_name, NULL, &len); - break; - case OID_at_serialNumber: - x509_rdn_to_der(oid, tag, a->serial_number, NULL, &len); - break; - case OID_at_dnQualifier: - x509_rdn_to_der(oid, tag, a->dn_qualifier, NULL, &len); - break; - default: - error_print(); - return -1; - } - } - asn1_sequence_header_to_der(len, out, outlen); - for (i = 0; i < a->count; i++) { - oid = a->oids[i]; - tag = a->tags[i]; - - switch (oid) { - case OID_at_countryName: - x509_rdn_to_der(oid, tag, a->country, out, outlen); - break; - case OID_at_stateOrProvinceName: - x509_rdn_to_der(oid, tag, a->state_or_province, out, outlen); - break; - case OID_at_localityName: - x509_rdn_to_der(oid, tag, a->locality, out, outlen); - break; - case OID_at_organizationName: - x509_rdn_to_der(oid, tag, a->org, out, outlen); - break; - case OID_at_organizationalUnitName: - x509_rdn_to_der(oid, tag, a->org_unit, out, outlen); - break; - case OID_at_commonName: - x509_rdn_to_der(oid, tag, a->common_name, out, outlen); - break; - case OID_at_serialNumber: - x509_rdn_to_der(oid, tag, a->serial_number, out, outlen); - break; - case OID_at_dnQualifier: - x509_rdn_to_der(oid, tag, a->dn_qualifier, out, outlen); - break; - default: - error_print(); - return -1; - } - } - return 1; -} - -int x509_public_key_info_set_sm2(X509_PUBLIC_KEY_INFO *a, const SM2_KEY *sm2_key) -{ - if (!a || !sm2_key) { - error_print(); - return -1; - } - memset(a, 0, sizeof(X509_PUBLIC_KEY_INFO)); - a->algor_oid = OID_x9_62_ecPublicKey; - a->curve_oid = OID_sm2; - sm2_set_public_key(&a->sm2_key, (uint8_t *)&sm2_key->public_key); - return 1; -} - -int x509_public_key_info_to_der(const X509_PUBLIC_KEY_INFO *a, uint8_t **out, size_t *outlen) -{ - if (sm2_public_key_info_to_der(&a->sm2_key, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_public_key_info_from_der(X509_PUBLIC_KEY_INFO *a, const uint8_t **in, size_t *inlen) -{ - int ret; - if ((ret = sm2_public_key_info_from_der(&a->sm2_key, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - a->algor_oid = OID_x9_62_ecPublicKey; - a->curve_oid = OID_sm2; - return 1; -} - -int x509_public_key_info_print(FILE *fp, const X509_PUBLIC_KEY_INFO *a, int format, int indent) -{ - format_print(fp, format, indent, "Algorithm : %s\n", asn1_object_identifier_name(a->algor_oid)); - format_print(fp, format, indent, "Parameters : %s\n", asn1_object_identifier_name(a->curve_oid)); - format_print(fp, format, indent, "PublicKey\n"); - sm2_point_print(fp, &a->sm2_key.public_key, format, indent + 4); - return 1; -} - - -// X.509 扩展的OID实际上在OID模块中并没有,我们应该在这个模块中独立给出 - - - -// DER_id_ce[] = 0x55,0x1D, - -static const uint8_t DER_x509_ce[] = { 0x55, 0x1d }; - - -static const struct { - int der; - int oid; - char *name; -} ce_oids[] = { - { 35, OID_ce_authorityKeyIdentifier, "AuthorityKeyIdentifier" }, - { 14, OID_ce_subjectKeyIdentifier, "SubjectKeyIdentifier" }, - { 15, OID_ce_keyUsage, "KeyUsage" }, - { 32, OID_ce_certificatePolicies, "CertificatePolicies" }, - { 33, OID_ce_policyMappings, "PolicyMappings" }, - { 17, OID_ce_subjectAltName, "SubjectAltName" }, - { 18, OID_ce_issuerAltName, "IssuerAltName" }, - { 9, OID_ce_subjectDirectoryAttributes, "SubjectDirectoryAttributes" }, - { 19, OID_ce_basicConstraints, "BasicConstraints" }, - { 30, OID_ce_nameConstraints, "NameConstraints" }, - { 36, OID_ce_policyConstraints, "PolicyConstraints" }, - { 37, OID_ce_extKeyUsage, "ExtKeyUsage" }, - { 31, OID_ce_crlDistributionPoints, "CRLDistributionPoints" }, - { 54, OID_ce_inhibitAnyPolicy, "InhibitAnyPolicy" }, - { 46, OID_ce_freshestCRL, "FreshestCRL" }, -}; - -const char *x509_extension_oid_name(int oid) -{ - int i; - for (i = 0; i < sizeof(ce_oids)/sizeof(ce_oids[0]); i++) { - if (oid == ce_oids[i].oid) { - return ce_oids[i].name; - } - } - return NULL; -} - -int x509_extension_oid_to_der(int oid, uint8_t **out, size_t *outlen) -{ - uint8_t octets[3] = { 0x55, 0x1d, 0 }; - int i; - - for (i = 0; i < sizeof(ce_oids)/sizeof(ce_oids[0]); i++) { - if (oid == ce_oids[i].oid) { - octets[2] = ce_oids[i].der; - } - } - if (octets[2] == 0) { - return -1; - } - asn1_tag_to_der(ASN1_TAG_OBJECT_IDENTIFIER, out, outlen); - asn1_length_to_der(sizeof(octets), out, outlen); - asn1_data_to_der(octets, sizeof(octets), out, outlen); - return 1; -} - -/* -应该首先对OID进行基本的解析,判断正确性,并获得nodes用于显示 -然后可以根据应用场景对octets进行解析,以获得name -*/ -int x509_extension_oid_from_der(int *oid, uint32_t *nodes, size_t *nodes_count, const uint8_t **pin, size_t *pinlen) -{ - int ret; - size_t len; - const uint8_t *octets; - int i; - const uint8_t *in = *pin; - size_t inlen = *pinlen; - - if ((ret = asn1_object_identifier_from_der(oid, nodes, nodes_count, pin, pinlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if ((ret = asn1_tag_from_der(ASN1_TAG_OBJECT_IDENTIFIER, &in, &inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_length_from_der(&len, &in, &inlen) != 1 - || asn1_data_from_der(&octets, len, &in, &inlen) != 1) { - error_print(); - return -1; - } - if (len == 3 && octets[0] == 0x55 && octets[1] == 0x1d) { - for (i = 0; i < sizeof(ce_oids)/sizeof(ce_oids[0]); i++) { - if (octets[2] == ce_oids[i].der) { - *oid = ce_oids[i].oid; - return 1; - } - } - } - return ret; -} - -// out != NULL 时,data 不可以为 NULL -int x509_extension_to_der(int oid, int is_critical, const uint8_t *data, size_t datalen, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (x509_extension_oid_to_der(oid, NULL, &len) != 1 - || (is_critical >= 0 && asn1_boolean_to_der(is_critical, NULL, &len) != 1) - || asn1_octet_string_to_der(data, datalen, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_extension_oid_to_der(oid, out, outlen) != 1 - || (is_critical >= 0 && asn1_boolean_to_der(is_critical, out, outlen) != 1) - || asn1_octet_string_to_der(data, datalen, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_extension_from_der(int *oid, uint32_t *nodes, size_t *nodes_count, - int *is_critical, const uint8_t **data, size_t *datalen, - const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *seq; - size_t seqlen; - - if ((ret = asn1_sequence_from_der(&seq, &seqlen, in, inlen)) != 1) { - return ret; - } - - *is_critical = ASN1_FALSE; - if (x509_extension_oid_from_der(oid, nodes, nodes_count, &seq, &seqlen) != 1 // FIXME: 这里检查OID应该是从一个子集里面检索 - || asn1_boolean_from_der(is_critical, &seq, &seqlen) < 0 - || asn1_octet_string_from_der(data, datalen, &seq, &seqlen) != 1 - || asn1_length_is_zero(seqlen) != 1) { - error_print(); - return -1; - } - if (*datalen <= 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_extension_print(FILE *fp, int oid, const uint32_t *nodes, size_t nodes_count, - int is_critical, const uint8_t *data, size_t datalen, - int format, int indent) -{ - const char *ext_name = x509_extension_oid_name(oid); - if (!ext_name) { - ext_name = "Unknown Extension"; - } - format_print(fp, format, indent, "%s (", ext_name); - while (nodes_count-- > 1) { - fprintf(fp, "%d.", *nodes++); - } - fprintf(fp, "%d)\n", *nodes); - indent += 4; - - if (is_critical >= 0) { - format_print(fp, format, indent, "crtical: %s\n", is_critical ? "true" : "false"); - } - - switch (oid) { - case OID_ce_authorityKeyIdentifier: return x509_authority_key_identifier_print(fp, data, datalen, format, indent); - case OID_ce_basicConstraints: return x509_basic_constraints_print(fp, data, datalen, format, indent); - case OID_ce_keyUsage: return x509_key_usage_print(fp, data, datalen, format, indent); - case OID_ce_subjectKeyIdentifier: return x509_subject_key_identifier_print(fp, data, datalen, format, indent); - case OID_ce_extKeyUsage: return x509_ext_key_usage_print(fp, data, datalen, format, indent); - case OID_ce_policyConstraints: return x509_policy_constraints_print(fp, data, datalen, format, indent); - default: - format_bytes(fp, format, indent, "extnValue : ", data, datalen); - } - return 1; -} - -int x509_extensions_print(FILE *fp, const X509_EXTENSIONS *a, int format, int indent) -{ - int ret; - int oid; - uint32_t nodes[32]; - size_t nodes_count; - int is_critical; - const uint8_t *data; - size_t datalen; - const uint8_t *next = a->data; - - format_print(fp, format, indent, "Extensions\n"); indent += 4; - for (;;) { - if ((ret = x509_extensions_get_next_item(a, &next, - &oid, nodes, &nodes_count, &is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - x509_extension_print(fp, oid, nodes, nodes_count, is_critical, data, datalen, format, indent); - } - return 1; -} - -int x509_extensions_to_der(const X509_EXTENSIONS *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - asn1_sequence_to_der(a->data, a->datalen, NULL, &len); - asn1_explicit_header_to_der(3, len, out, outlen); - asn1_sequence_to_der(a->data, a->datalen, out, outlen); - return 1; -} - -int x509_extensions_from_der(X509_EXTENSIONS *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_explicit_from_der(3, &data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_sequence_copy_from_der(512, a->data, &a->datalen, &data, &datalen) != 1 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - // FIXME:检查extensions的格式是否正确 - return 1; -} - -int x509_extensions_add_item(X509_EXTENSIONS *a, - int oid, int is_critical, const uint8_t *data, size_t datalen) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_extension_to_der(oid, is_critical, data, datalen, &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - -int x509_extensions_get_next_item(const X509_EXTENSIONS *a, const uint8_t **next, - int *oid, uint32_t *nodes, size_t *nodes_count, - int *is_critical, const uint8_t **data, size_t *datalen) -{ - int ret; - size_t len = a->datalen; // FIXME: len赋值不对 - if ((ret = x509_extension_from_der(oid, nodes, nodes_count, is_critical, data, datalen, next, &len)) != 1) { - if (ret < 0) error_print(); - return ret; - } - return 1; -} - -int x509_certificate_add_extension(X509_CERTIFICATE *a, int oid, int is_critical, - const uint8_t *data, size_t datalen) -{ - if (x509_extensions_add_item(&a->tbs_certificate.extensions, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_extension_from_oid(const X509_CERTIFICATE *a, int oid, - int *is_critical, const uint8_t **data, size_t *datalen) -{ - int ret; - const X509_EXTENSIONS *ext; - const uint8_t *next = NULL; - int rid; - uint32_t nodes[16]; - size_t nodes_count; - - for (;;) { - if ((ret = x509_extensions_get_next_item(&a->tbs_certificate.extensions, &next, - &rid, nodes, &nodes_count, is_critical, data, datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (rid == oid) { - return 1; - } - } - return 0; -} - -// 这里用来打印的到底是解析后的内容,还是解析之前的DER呢? -// 而且这个打印函数应该能够支持所有类型的打印 - -int x509_tbs_certificate_to_der(const X509_TBS_CERTIFICATE *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - if (x509_version_to_der(a->version, NULL, &len) != 1 - || asn1_integer_to_der(a->serial_number, a->serial_number_len, NULL, &len) != 1 - || x509_signature_algor_to_der(a->signature_algor, NULL, &len) != 1 - || x509_name_to_der(&a->issuer, NULL, &len) != 1 - || x509_validity_to_der(&a->validity, NULL, &len) != 1 - || x509_name_to_der(&a->subject, NULL, &len) != 1 - || x509_public_key_info_to_der(&a->subject_public_key_info, NULL, &len) != 1 - || asn1_implicit_bit_string_to_der(1, a->issuer_unique_id, a->issuer_unique_id_len * 8, NULL, &len) < 0 - || asn1_implicit_bit_string_to_der(2, a->subject_unique_id, a->subject_unique_id_len * 8, NULL, &len) <0 - || x509_extensions_to_der(&a->extensions, NULL, &len) < 0) { - error_print(); - return -1; - } - if (asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_version_to_der(a->version, out, outlen) != 1 - || asn1_integer_to_der(a->serial_number, a->serial_number_len, out, outlen) != 1 - || x509_signature_algor_to_der(a->signature_algor, out, outlen) != 1 - || x509_name_to_der(&a->issuer, out, outlen) != 1 - || x509_validity_to_der(&a->validity, out, outlen) != 1 - || x509_name_to_der(&a->subject, out, outlen) != 1 - || x509_public_key_info_to_der(&a->subject_public_key_info, out, outlen) != 1 - || asn1_implicit_bit_string_to_der(1, a->issuer_unique_id, a->issuer_unique_id_len * 8, out, outlen) < 0 - || asn1_implicit_bit_string_to_der(2, a->subject_unique_id, a->subject_unique_id_len * 8, out, outlen) < 0 - || x509_extensions_to_der(&a->extensions, out, outlen) < 0) { - error_print(); - return -1; - } - - return 1; -} - -int x509_tbs_certificate_from_der(X509_TBS_CERTIFICATE *a, const uint8_t **in, size_t *inlen) -{ - int is_ver, is_ext; - const uint8_t *ver, *exts; - size_t verlen, extslen; - - int ret; - const uint8_t *data; - size_t datalen; - const uint8_t *serial_number; - const uint8_t *issuer_unique_id = NULL; - const uint8_t *subject_unique_id = NULL; - uint32_t nodes[32]; - size_t nodes_count; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - - memset(a, 0, sizeof(*a)); - - size_t issuer_unique_id_nbits; - size_t subject_unique_id_nbits; - - if (x509_version_from_der(&a->version, &data, &datalen) != 1 - || asn1_integer_from_der(&serial_number, &a->serial_number_len, &data, &datalen) != 1 - || x509_signature_algor_from_der(&a->signature_algor, nodes, &nodes_count, &data, &datalen) != 1 - || x509_name_from_der(&a->issuer, &data, &datalen) != 1 - || x509_validity_from_der(&a->validity, &data, &datalen) != 1 - || x509_name_from_der(&a->subject, &data, &datalen) != 1 - || x509_public_key_info_from_der(&a->subject_public_key_info, &data, &datalen) != 1 - || asn1_implicit_bit_string_from_der(1, &issuer_unique_id, &issuer_unique_id_nbits, &data, &datalen) < 0 - || asn1_implicit_bit_string_from_der(2, &subject_unique_id, &subject_unique_id_nbits, &data, &datalen) < 0 - || (is_ext = x509_extensions_from_der(&a->extensions, &data, &datalen)) < 0 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - - // FIXME: 应该提供了检查函数,可以返回错误行数 - if (a->serial_number_len > 20 - || issuer_unique_id_nbits != 32 * 8 - || subject_unique_id_nbits != 32 * 8) { - - error_print(); - return -1; - } - - a->issuer_unique_id_len = issuer_unique_id_nbits/8; - a->subject_unique_id_len = subject_unique_id_nbits/8; - - - // asn1_implicit_bit_string_from_der 返回的是比特长度! - // 应该改变 issue - - - // FIXME: 这几个都应该用copy的方式 - memcpy(a->serial_number, serial_number, a->serial_number_len); - if (issuer_unique_id) { - memcpy(a->issuer_unique_id, issuer_unique_id, a->issuer_unique_id_len); - } - if (subject_unique_id) { - memcpy(a->subject_unique_id, subject_unique_id, a->subject_unique_id_len); - } - - return 1; -} - -int x509_certificate_to_der(const X509_CERTIFICATE *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (x509_tbs_certificate_to_der(&a->tbs_certificate, NULL, &len) != 1 - || x509_signature_algor_to_der(a->signature_algor, NULL, &len) != 1 - || asn1_bit_string_to_der(a->signature, a->signature_len * 8, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_tbs_certificate_to_der(&a->tbs_certificate, out, outlen) != 1 - || x509_signature_algor_to_der(a->signature_algor, out, outlen) != 1 - || asn1_bit_string_to_der(a->signature, a->signature_len * 8, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_to_pem(const X509_CERTIFICATE *a, FILE *fp) -{ - uint8_t buf[1024]; - uint8_t *p = buf; - size_t len = 0; - - if (x509_certificate_to_der(a, &p, &len) != 1) { - error_print(); - return -1; - } - if (pem_write(fp, "CERTIFICATE", buf, len) <= 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_from_der(X509_CERTIFICATE *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - const uint8_t *sig; - size_t sig_nbits; - uint32_t nodes[32]; - size_t nodes_count; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - memset(a, 0, sizeof(X509_CERTIFICATE)); - if (x509_tbs_certificate_from_der(&a->tbs_certificate, &data, &datalen) != 1) { - error_print(); - return -1; - } - if (x509_signature_algor_from_der(&a->signature_algor, nodes, &nodes_count, &data, &datalen) != 1) { - error_print(); - int i; - for (i = 0; i < nodes_count; i++) { - printf("%d ", (int)nodes[i]); - } - printf("\n"); - return -1; - } - if (asn1_bit_string_from_der(&sig, &sig_nbits, &data, &datalen) != 1) { - error_print(); - return -1; - } - if (asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - a->signature_len = (sig_nbits + 7)/8; - memcpy(a->signature, sig, a->signature_len); - return 1; -} - -int x509_certificate_from_pem(X509_CERTIFICATE *a, FILE *fp) -{ - int ret; - uint8_t buf[1024]; - const uint8_t *cp = buf; - size_t len; - - if ((ret = pem_read(fp, "CERTIFICATE", buf, &len)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_certificate_from_der(a, &cp, &len) != 1 - || len > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_print(FILE *fp, const X509_CERTIFICATE *a, int format, int indent) -{ - const X509_TBS_CERTIFICATE *tbs = &a->tbs_certificate; - size_t i; - - format_print(fp, format, indent, "Certificate\n"); - indent += 4; - format_print(fp, format, indent, "Version : %s (%d)\n", x509_version_name(tbs->version), tbs->version); - format_bytes(fp, format, indent, "SerialNumber : ", tbs->serial_number, tbs->serial_number_len); - format_print(fp, format, indent, "SigantureAlgorithm : %s\n", asn1_object_identifier_name(tbs->signature_algor)); - format_print(fp, format, indent, "Issuer\n"); - x509_name_print(fp, &tbs->issuer, format, indent + 4); - format_print(fp, format, indent, "Validity\n"); - x509_validity_print(fp, &tbs->validity, format, indent + 4); - format_print(fp, format, indent, "Subject\n"); - x509_name_print(fp, &tbs->subject, format, indent + 4); - format_print(fp, format, indent, "SubjectPublicKeyInfo\n"); - x509_public_key_info_print(fp, &tbs->subject_public_key_info, format, indent + 4); - format_print(fp, format, indent, "SigantureAlgorithm : %s\n", asn1_object_identifier_name(a->signature_algor)); - format_bytes(fp, format, indent, "Signature : ", a->signature, a->signature_len); - x509_extensions_print(fp, &a->tbs_certificate.extensions, format, indent); - return 1; -} - -int x509_signature_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen) -{ - if (asn1_bit_string_to_der(a, alen * 8, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_signature_copy_from_der(size_t maxlen, uint8_t *a, size_t *alen, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *bits; - size_t nbits; - - if ((ret = asn1_bit_string_from_der(&bits, &nbits, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (nbits % 8 != 0) { - error_print(); - return -1; - } - *alen = nbits / 8; - if (*alen > maxlen) { - error_print(); - return -1; - } - memcpy(a, bits, *alen); - return 1; -} - - - -/* -from RFC 2986 - -CertificationRequest ::= SEQUENCE { - certificationRequestInfo CertificationRequestInfo, - signatureAlgorithm AlgorithmIdentifier, - signature BIT STRING -} - -CertificationRequestInfo ::= SEQUENCE { - version INTEGER { v1(0) }, - subject Name, - subjectPKInfo SubjectPublicKeyInfo, - attributes [0] IMPLICIT SET OF Attribute -} -*/ - -int x509_cert_request_set_sm2(X509_CERT_REQUEST *a, const X509_NAME *subject, const SM2_KEY *sm2_key) -{ - memset(a, 0, sizeof(*a)); - a->req_info.version = X509_version_v1; - a->req_info.subject = *subject; - if (x509_public_key_info_set_sm2(&a->req_info.subject_public_key_info, sm2_key) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_info_to_der(const X509_CERT_REQUEST_INFO *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (asn1_int_to_der(a->version, NULL, &len) != 1 - || x509_name_to_der(&a->subject, NULL, &len) != 1 - || x509_public_key_info_to_der(&a->subject_public_key_info, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(a->version, out, outlen) != 1 - || x509_name_to_der(&a->subject, out, outlen) != 1 - || x509_public_key_info_to_der(&a->subject_public_key_info, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_info_from_der(X509_CERT_REQUEST_INFO *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - const uint8_t *attrs; - size_t attrslen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_int_from_der(&a->version, &data, &datalen) != 1 - || x509_name_from_der(&a->subject, &data, &datalen) != 1 - || x509_public_key_info_from_der(&a->subject_public_key_info, &data, &datalen) != 1 - || asn1_implicit_from_der(0, &attrs, &attrslen, &data, &datalen) < 0 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_info_print(FILE *fp, const X509_CERT_REQUEST_INFO *a, int format, int indent) -{ - format_print(fp, format, indent, "CertificationRequestInfo\n"); - indent += 4; - format_print(fp, format, indent, "version: %s (%d)\n", x509_version_name(a->version), a->version); - format_print(fp, format, indent, "subject\n"); - x509_name_print(fp, &a->subject, format, indent+4); - format_print(fp, format, indent, "subjectPublicKeyInfo\n"); - x509_public_key_info_print(fp, &a->subject_public_key_info, format, indent+4); - - // FIXME: attributes 没有处理 - return 1; -} - -int x509_cert_request_to_der(const X509_CERT_REQUEST *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (x509_cert_request_info_to_der(&a->req_info, NULL, &len) != 1 - || x509_signature_algor_to_der(a->signature_algor, NULL, &len) != 1 - || x509_signature_to_der(a->signature, a->signature_len, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_cert_request_info_to_der(&a->req_info, out, outlen) != 1 - || x509_signature_algor_to_der(a->signature_algor, out, outlen) != 1 - || x509_signature_to_der(a->signature, a->signature_len, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_from_der(X509_CERT_REQUEST *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - const uint8_t *sig; - size_t siglen; - uint32_t nodes[32]; - size_t nodes_count; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_cert_request_info_from_der(&a->req_info, &data, &datalen) != 1 - || x509_signature_algor_from_der(&a->signature_algor, nodes, &nodes_count, &data, &datalen) != 1 - || x509_signature_copy_from_der(128, a->signature, &a->signature_len, &data, &datalen) != 1 - || asn1_length_is_zero(datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_to_pem(const X509_CERT_REQUEST *a, FILE *fp) -{ - uint8_t buf[512]; - uint8_t *p = buf; - size_t len = 0; - - if (x509_cert_request_to_der(a, &p, &len) != 1) { - error_print(); - return -1; - } - if (pem_write(fp, "CERTIFICATE REQUEST", buf, len) <= 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_from_pem(X509_CERT_REQUEST *a, FILE *fp) -{ - uint8_t buf[512]; - const uint8_t *cp = buf; - size_t len; - - if (pem_read(fp, "CERTIFICATE REQUEST", buf, &len) != 1) { - error_print(); - return -1; - } - if (x509_cert_request_from_der(a, &cp, &len) != 1 - || asn1_length_is_zero(len) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_print(FILE *fp, const X509_CERT_REQUEST *a, int format, int indent) -{ - size_t i; - - format_print(fp, format, indent, "CertificationRequest\n"); - indent += 4; - x509_cert_request_info_print(fp, &a->req_info, format, indent); - format_print(fp, format, indent, "signatureAlgorithm: %s\n", asn1_object_identifier_name(a->signature_algor)); - format_bytes(fp, format, indent, "signature: ", a->signature, a->signature_len); - return 1; -} - -int x509_cert_request_sign_sm2(X509_CERT_REQUEST *a, const SM2_KEY *sm2_key) -{ - SM2_SIGN_CTX ctx; - uint8_t tbs[1024]; - uint8_t *p = tbs; - size_t tbslen = 0; - - a->signature_algor = OID_sm2sign_with_sm3; - if (x509_cert_request_info_to_der(&a->req_info, &p, &tbslen) != 1) { - error_print(); - return -1; - } - if (sm2_sign_init(&ctx, sm2_key, SM2_DEFAULT_ID) != 1 - || sm2_sign_update(&ctx, tbs, tbslen) != 1 - || sm2_sign_finish(&ctx, a->signature, &a->signature_len) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_request_verify(const X509_CERT_REQUEST *a) -{ - int ret; - const SM2_KEY *sm2_key; - SM2_SIGN_CTX ctx; - uint8_t tbs[1024]; - uint8_t *p = tbs; - size_t tbslen = 0; - - if (x509_cert_request_info_to_der(&a->req_info, &p, &tbslen) != 1) { - error_print(); - return -1; - } - - sm2_key = &a->req_info.subject_public_key_info.sm2_key; - - if (sm2_verify_init(&ctx, sm2_key, SM2_DEFAULT_ID) != 1 - || sm2_verify_update(&ctx, tbs, tbslen) != 1 - || (ret = sm2_verify_finish(&ctx, a->signature, a->signature_len)) < 0) { - error_print(); - return -1; - } - return ret; -} diff --git a/src/x509_cer.c b/src/x509_cer.c new file mode 100644 index 00000000..054174d6 --- /dev/null +++ b/src/x509_cer.c @@ -0,0 +1,1229 @@ +/* + * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +const char *x509_version_name(int version) +{ + switch (version) { + case X509_version_v1: return "v1"; + case X509_version_v2: return "v2"; + case X509_version_v3: return "v3"; + } + return NULL; +} + +int x509_explicit_version_to_der(int index, int version, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + + if (version < 0) { + return 0; + } + if (!x509_version_name(version)) { + error_print(); + return -1; + } + if (asn1_int_to_der(version, NULL, &len) != 1 + || asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_version_from_der(int index, int *version, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_explicit_from_der(index, &d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + else *version = X509_version_v1; + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (!x509_version_name(*version)) { + error_print(); + return -1; + } + return 1; +} + +/* + from RFC 5280 section 4.1.2.5 + + CAs conforming to this profile MUST always encode certificate + validity dates through the year 2049 as UTCTime; certificate validity + dates in 2050 or later MUST be encoded as GeneralizedTime. + Conforming applications MUST be able to process validity dates that + are encoded in either UTCTime or GeneralizedTime. + + To indicate that a certificate has no well-defined expiration date, + the notAfter SHOULD be assigned the GeneralizedTime value of + 99991231235959Z. +*/ +int x509_time_to_der(time_t tv, uint8_t **out, size_t *outlen) +{ + int ret; + struct tm tm_val; + + gmtime_r(&tv, &tm_val); + if (tm_val.tm_year < 2050 - 1900) { + if ((ret = asn1_utc_time_to_der(tv, out, outlen)) != 1) { + if (ret < 0) error_print(); + } + } else { + if ((ret = asn1_generalized_time_to_der(tv, out, outlen)) !=1) { + if (ret < 0) error_print(); + } + } + return ret; +} + +int x509_time_from_der(time_t *tv, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_utc_time_from_der(tv, in, inlen)) < 0) { + error_print(); + return -1; + } else if (ret) { + return 1; + } + + if ((ret = asn1_generalized_time_from_der(tv, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_validity_add_days(time_t *not_after, time_t not_before, int days) +{ + struct tm tm_val; + if (days < X509_VALIDITY_MIN_DAYS + || days > X509_VALIDITY_MAX_DAYS) { + error_print(); + return -1; + } + gmtime_r(¬_before, &tm_val); + tm_val.tm_mday += days; + *not_after = mktime(&tm_val); + return 1; +} + +int x509_validity_to_der(time_t not_before, time_t not_after, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_time_to_der(not_before, NULL, &len) != 1 + || x509_time_to_der(not_after, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_time_to_der(not_before, out, outlen) != 1 + || x509_time_to_der(not_after, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_validity_from_der(time_t *not_before, time_t *not_after, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_time_from_der(not_before, &d, &dlen) != 1 + || x509_time_from_der(not_after, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (*not_before >= *not_after) { + error_print(); + return -1; + } + return 1; +} + +int x509_validity_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + time_t tv; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_time_from_der(&tv, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "notBefore : %s\n", ctime(&tv)); + if (x509_time_from_der(&tv, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "notAfter : %s\n", ctime(&tv)); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + + +static const struct { + int oid; + int is_printable_string_only; + int minlen; + int maxlen; +} x509_name_types[] = { + { OID_at_country_name, 1, 2, 2 }, + { OID_at_state_or_province_name, 0, 1, X509_ub_state_name }, + { OID_at_locality_name, 0, 1, X509_ub_locality_name }, + { OID_at_organization_name, 0, 1, X509_ub_organization_name }, + { OID_at_organizational_unit_name, 0, 1, X509_ub_organizational_unit_name }, + { OID_at_common_name, 0, 1, X509_ub_common_name }, + { OID_at_serial_number, 1, 1, X509_ub_serial_number }, + { OID_at_dn_qualifier, 1, 1, 64 }, // max length unspecified in RFC 5280 + { OID_at_title, 0, 1, X509_ub_title }, + { OID_at_surname, 0, 1, X509_ub_name }, + { OID_at_given_name, 0, 1, X509_ub_name }, + { OID_at_initials, 0, 1, X509_ub_name }, + { OID_at_generation_qualifier, 0, 1, X509_ub_name }, + { OID_at_pseudonym, 0, 1, X509_ub_pseudonym }, +}; + +static const int x509_name_types_count + = sizeof(x509_name_types)/sizeof(x509_name_types[0]); + +int x509_attr_type_and_value_check(int oid, int tag, const uint8_t *val, size_t vlen) +{ + int i; + for (i = 0; i < x509_name_types_count; i++) { + if (oid == x509_name_types[i].oid) { + if (x509_name_types[i].is_printable_string_only + && tag != ASN1_TAG_PrintableString) { + error_print(); + return -1; + } + if (x509_directory_name_check_ex(tag, val, vlen, + x509_name_types[i].minlen, x509_name_types[i].maxlen) != 1) { + error_print(); + return -1; + } + return 1; + } + } + return 0; +} + +int x509_attr_type_and_value_to_der(int oid, int tag, const uint8_t *val, size_t vlen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_attr_type_and_value_check(oid, tag, val, vlen) != 1 + || x509_name_type_to_der(oid, NULL, &len) != 1 + || x509_directory_name_to_der(tag, val, vlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_name_type_to_der(oid, out, outlen) != 1 + || x509_directory_name_to_der(tag, val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_attr_type_and_value_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_name_type_from_der(oid, &d, &dlen) != 1 + || x509_directory_name_from_der(tag, val, vlen, &d, &dlen) != 1 + || x509_attr_type_and_value_check(*oid, *tag, *val, *vlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_attr_type_and_value_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid, tag; + const uint8_t *val; + size_t vlen; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if (x509_name_type_from_der(&oid, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "type", x509_name_type_name(oid), NULL, 0); + if (x509_directory_name_from_der(&tag, &val, &vlen, &d, &dlen) != 1) goto err; + x509_directory_name_print(fp, fmt, ind, "value", tag, val, vlen); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_rdn_to_der(int oid, int tag, const uint8_t *val, size_t vlen, + const uint8_t *more, size_t morelen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_attr_type_and_value_to_der(oid, tag, val, vlen, NULL, &len) != 1 + || asn1_data_to_der(more, morelen, NULL, &len) < 0 + || asn1_set_header_to_der(len, out, outlen) != 1 + || x509_attr_type_and_value_to_der(oid, tag, val, vlen, out, outlen) != 1 + || asn1_data_to_der(more, morelen, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_rdn_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, + const uint8_t **more, size_t *morelen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_set_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_attr_type_and_value_from_der(oid, tag, val, vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (dlen) { + *more = d; + *morelen = dlen; + // TODO: check more,morelen + } else { + *more = NULL; + *morelen = 0; + } + return 1; +} + +int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_attr_type_and_value_print(fp, fmt, ind, "AttributeTypeAndValue", p, len); + } + format_print(fp, fmt, ind, "\n"); + return 1; +} + +int x509_name_add_rdn(uint8_t *d, size_t *dlen, size_t maxlen, + int oid, int tag, const uint8_t *val, size_t vlen, + const uint8_t *more, size_t morelen) +{ + uint8_t *p; + size_t len = 0; + + if (x509_rdn_to_der(oid, tag, val, len, NULL, 0, NULL, &len) != 1) { + error_print(); + return -1; + } + if (*dlen + len + morelen > maxlen) { + error_print(); + return -1; + } + if (x509_rdn_to_der(oid, tag, val, len, NULL, 0, &d, dlen) != 1 + || asn1_data_to_der(more, morelen, &d, dlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_name_add_country_name(uint8_t *d, size_t *dlen, int maxlen, const char val[2]) +{ + return x509_name_add_rdn(d, dlen, maxlen, + OID_at_country_name, ASN1_TAG_PrintableString, (uint8_t *)val, 2, NULL, 0); +} + +int x509_name_add_state_or_province_name(uint8_t *d, size_t *dlen, int maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + return x509_name_add_rdn(d, dlen, maxlen, OID_at_state_or_province_name, tag, val, vlen, NULL, 0); +} + +int x509_name_add_locality_name(uint8_t *d, size_t *dlen, int maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + return x509_name_add_rdn(d, dlen, maxlen, OID_at_locality_name, tag, val, vlen, NULL, 0); +} + +int x509_name_add_organization_name(uint8_t *d, size_t *dlen, int maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + return x509_name_add_rdn(d, dlen, maxlen, OID_at_organization_name, tag, val, vlen, NULL, 0); +} + +int x509_name_add_organizational_unit_name(uint8_t *d, size_t *dlen, int maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + return x509_name_add_rdn(d, dlen, maxlen, OID_at_organizational_unit_name, tag, val, vlen, NULL, 0); +} + +int x509_name_add_common_name(uint8_t *d, size_t *dlen, int maxlen, + int tag, const uint8_t *val, size_t vlen) +{ + return x509_name_add_rdn(d, dlen, maxlen, OID_at_common_name, tag, val, vlen, NULL, 0); +} + +int x509_name_add_domain_component(uint8_t *d, size_t *dlen, int maxlen, + const char *val, size_t vlen) +{ + return x509_name_add_rdn(d, dlen, maxlen, OID_domain_component, ASN1_TAG_IA5String, (uint8_t *)val, vlen, NULL, 0); +} + +int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_rdn_print(fp, fmt, ind, "RelativeDistinguishedName", p, len); + } + return 1; +} + +int x509_name_get_printable(const uint8_t *d, size_t dlen, char *str, size_t maxlen) +{ + error_print(); + return -1; +} + +int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen) +{ + error_print(); + return -1; +} + +int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen) +{ + error_print(); + return -1; +} + +int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_algor_print(fp, fmt, ind, "algorithm", p, len); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "subjectPublicKey: ", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_ext_id_to_der(oid, NULL, &len) != 1 + || asn1_boolean_to_der(critical, NULL, &len) < 0 + || asn1_octet_string_to_der(val, vlen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_ext_id_to_der(oid, out, outlen) != 1 + || asn1_boolean_to_der(critical, out, outlen) != 1 + || asn1_octet_string_to_der(val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_ext_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, + int *critical, const uint8_t **val, size_t *vlen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + *critical = 0; + if (x509_ext_id_from_der(oid, nodes, nodes_cnt, &d, &dlen) != 1 + || asn1_boolean_from_der(critical, &d, &dlen) < 0 + || asn1_octet_string_from_der(val, vlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, oid, critical; + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *val; + size_t vlen; + + const uint8_t *p; + size_t len; + int ival; + const char *name; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if (x509_ext_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "extnID", x509_ext_id_name(oid), nodes, nodes_cnt); + if ((ret = asn1_boolean_from_der(&critical, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "critical: %s\n", critical ? "True" : "False"); + if (asn1_octet_string_from_der(&val, &vlen, &d, &dlen) != 1) goto err; + + switch (oid) { + case OID_ce_subject_key_identifier: + if (asn1_octet_string_from_der(&p, &len, &val, &vlen)) { + error_print(); + return -1; + } + break; + case OID_ce_key_usage: + if (asn1_bits_from_der(&ival, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_inhibit_any_policy: + if (asn1_int_from_der(&ival, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_undef: + p = val; + len = vlen; + vlen = 0; + break; + default: + if (asn1_sequence_from_der(&p, &len, &val, &vlen) != 1) { + error_print(); + return -1; + } + } + if (asn1_length_is_zero(vlen) != 1) { + error_print(); + return -1; + } + + name = x509_ext_id_name(oid); + + switch (oid) { + case OID_ce_authority_key_identifier: return x509_authority_key_identifier_print(fp, fmt, ind, name, p, len); + case OID_ce_subject_key_identifier: return format_bytes(fp, fmt, ind, name, p, len); + case OID_ce_key_usage: return x509_key_usage_print(fp, fmt, ind, name, ival); + case OID_ce_certificate_policies: return x509_certificate_policies_print(fp, fmt, ind, name, p, len); + case OID_ce_policy_mappings: return x509_policy_mappings_print(fp, fmt, ind, name, p, len); + case OID_ce_subject_alt_name: return x509_general_names_print(fp, fmt, ind, name, p, len); + case OID_ce_issuer_alt_name: return x509_general_names_print(fp, fmt, ind, name, p, len); + case OID_ce_subject_directory_attributes: return x509_attributes_print(fp, fmt, ind, name, p, len); + case OID_ce_basic_constraints: return x509_basic_constraints_print(fp, fmt, ind, name, p, len); + case OID_ce_name_constraints: return x509_name_constraints_print(fp, fmt, ind, name, p, len); + case OID_ce_policy_constraints: return x509_policy_constraints_print(fp, fmt, ind, name, p, len); + case OID_ce_ext_key_usage: return x509_ext_key_usage_print(fp, fmt, ind, name, p, len); + case OID_ce_crl_distribution_points: return x509_crl_distribution_points_print(fp, fmt, ind, name, p, len); + case OID_ce_inhibit_any_policy: format_print(fp, fmt, ind, "%s: %d\n", name, ival); + case OID_ce_freshest_crl: return x509_freshest_crl_print(fp, fmt, ind, name, p, len); + default: format_bytes(fp, fmt, ind, "extnValue", p, len); + } + return 1; +err: + error_print(); + return -1; +} + +int x509_explicit_exts_to_der(int index, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_sequence_to_der(d, dlen, NULL, &len) != 1 + || asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || asn1_sequence_to_der(d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_exts_from_der(int index, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_sequence_from_der(d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_get_count(const uint8_t *d, size_t dlen, size_t *cnt) +{ + return asn1_types_get_count(d, dlen, ASN1_TAG_SEQUENCE, cnt); +} + +int x509_exts_get_ext_by_index(const uint8_t *d, size_t dlen, int index, + int *oid, uint32_t *nodes, size_t *nodes_cnt, int *critical, + const uint8_t **val, size_t *vlen) +{ + error_print(); + return -1; +} + +int x509_exts_get_ext_by_oid(const uint8_t *d, size_t dlen, int oid, + int *critical, const uint8_t **val, size_t *vlen) +{ + return -1; +} + +int x509_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_ext_print(fp, fmt, ind, "Extension", p, len); + } + return 1; +} + +int x509_tbs_cert_to_der( + int version, + const uint8_t *serial, size_t serial_len, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t not_before, time_t not_after, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *issuer_unique_id, size_t issuer_unique_id_len, + const uint8_t *subject_unique_id, size_t subject_unique_id_len, + const uint8_t *exts, size_t exts_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_explicit_version_to_der(0, version, NULL, &len) < 0 + || asn1_integer_to_der(serial, serial_len, NULL, &len) != 1 + || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 + || asn1_sequence_to_der(issuer, issuer_len, NULL, &len) != 1 + || x509_validity_to_der(not_before, not_after, NULL, &len) != 1 + || asn1_sequence_to_der(subject, subject_len, NULL, &len) != 1 + || x509_public_key_info_to_der(subject_public_key, NULL, &len) != 1 + || asn1_implicit_bit_octets_to_der(1, issuer_unique_id, issuer_unique_id_len, NULL, &len) < 0 + || asn1_implicit_bit_octets_to_der(2, subject_unique_id, subject_unique_id_len, NULL, &len) < 0 + || x509_explicit_exts_to_der(3, exts, exts_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_explicit_version_to_der(0, version, out, outlen) < 0 + || asn1_integer_to_der(serial, serial_len, out, outlen) != 1 + || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 + || asn1_sequence_to_der(issuer, issuer_len, out, outlen) != 1 + || x509_validity_to_der(not_before, not_after, out, outlen) != 1 + || asn1_sequence_to_der(subject, subject_len, out, outlen) != 1 + || x509_public_key_info_to_der(subject_public_key, out, outlen) != 1 + || asn1_implicit_bit_octets_to_der(1, issuer_unique_id, issuer_unique_id_len, out, outlen) < 0 + || asn1_implicit_bit_octets_to_der(2, subject_unique_id, subject_unique_id_len, out, outlen) < 0 + || x509_explicit_exts_to_der(3, exts, exts_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_tbs_cert_from_der( + int *version, + const uint8_t **serial, size_t *serial_len, + int *signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *not_before, time_t *not_after, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **issuer_unique_id, size_t *issuer_unique_id_len, + const uint8_t **subject_unique_id, size_t *subject_unique_id_len, + const uint8_t **exts, size_t *exts_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_explicit_version_from_der(0, version, &d, &dlen) < 0 + || asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 + || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 + || asn1_sequence_from_der(issuer, issuer_len, &d, &dlen) != 1 + || x509_validity_from_der(not_before, not_after, &d, &dlen) != 1 + || asn1_sequence_from_der(subject, subject_len, &d, &dlen) != 1 + || x509_public_key_info_from_der(subject_public_key, &d, &dlen) != 1 + || asn1_implicit_bit_octets_from_der(1, issuer_unique_id, issuer_unique_id_len, &d, &dlen) < 0 + || asn1_implicit_bit_octets_from_der(2, subject_unique_id, subject_unique_id_len, &d, &dlen) < 0 + || x509_explicit_exts_from_der(3, exts, exts_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_tbs_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = x509_explicit_version_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "version: %s\n", x509_version_name(val)); + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "serialNumber", p, len); + if (x509_signature_algor_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "siganture: %s\n", x509_signature_algor_name(val)); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "issuer", d, dlen); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_validity_print(fp, fmt, ind, "validity", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "subject", d, dlen); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_info_print(fp, fmt, ind, "subjectPulbicKeyInfo", p, len); + if ((ret = asn1_implicit_bit_octets_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "issuerUniqueID", p, len); + if ((ret = asn1_implicit_bit_octets_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "subjectUniqueID", p, len); + if ((ret = x509_explicit_exts_from_der(3, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_exts_print(fp, fmt, ind, "extensions", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_certificate_to_der( + const uint8_t *tbs, size_t tbslen, // full TLV + int signature_algor, + const uint8_t *sig, size_t siglen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_data_to_der(tbs, tbslen, NULL, &len) != 1 + || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_data_to_der(tbs, tbslen, out, outlen) != 1 + || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_certificate_from_der( + const uint8_t **tbs, size_t *tbslen, // full TLV + int *signature_algor, + const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_any_from_der(tbs, tbslen, &d, &dlen) != 1 + || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 + || asn1_bit_octets_from_der(sig, siglen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + int val; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_tbs_cert_print(fp, fmt, ind, "tbsCertificate", p, len); + if (x509_signature_algor_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "signatureAlgorithm: %s\n", x509_signature_algor_name(val)); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "signatureValue", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; +err: + error_print(); + return -1; +} + +int x509_cert_sign( + uint8_t *cert, size_t *certlen, size_t maxlen, + int version, + const uint8_t *serial, size_t serial_len, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t not_before, time_t not_after, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *issuer_unique_id, size_t issuer_unique_id_len, + const uint8_t *subject_unique_id, size_t subject_unique_id_len, + const uint8_t *exts, size_t exts_len, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len) +{ + uint8_t tbs[1024]; + size_t tbslen = 0; + uint8_t *p = tbs; + size_t len = 0; + SM2_SIGN_CTX sign_ctx; + int sig_alg = OID_sm2sign_with_sm3; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + if (x509_tbs_cert_to_der(version, serial, serial_len, signature_algor, + issuer, issuer_len, not_before, not_after, + subject, subject_len, subject_public_key, + issuer_unique_id, issuer_unique_id_len, + subject_unique_id, subject_unique_id_len, + exts, exts_len, NULL, &len) != 1 + || asn1_length_le(len, sizeof(tbs)) != 1 + || x509_tbs_cert_to_der(version, serial, serial_len, signature_algor, + issuer, issuer_len, not_before, not_after, + subject, subject_len, subject_public_key, + issuer_unique_id, issuer_unique_id_len, + subject_unique_id, subject_unique_id_len, + exts, exts_len, &p, &tbslen) != 1) { + error_print(); + return -1; + } + + if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 + || sm2_sign_update(&sign_ctx, tbs, tbslen) != 1 + || sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) { + memset(&sign_ctx, 0, sizeof(sign_ctx)); + error_print(); + return -1; + } + memset(&sign_ctx, 0, sizeof(sign_ctx)); + + *certlen = len = 0; + if (x509_certificate_to_der(tbs, tbslen, sig_alg, sig, siglen, NULL, &len) != 1 + || asn1_length_le(len, maxlen) != 1 + || x509_certificate_to_der(tbs, tbslen, sig_alg, sig, siglen, &cert, certlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_verify(const uint8_t *a, size_t alen, + const SM2_KEY *pub_key, const char *signer_id, size_t signer_id_len) +{ + int ret; + const uint8_t *tbs; + size_t tbslen; + int sig_alg; + const uint8_t *sig; + size_t siglen; + SM2_SIGN_CTX verify_ctx; + + if (x509_certificate_from_der(&tbs, &tbslen, &sig_alg, &sig, &siglen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + if (sig_alg != OID_sm2sign_with_sm3) { + error_print(); + return -1; + } + if (sm2_verify_init(&verify_ctx, pub_key, signer_id, signer_id_len) != 1 + || sm2_verify_update(&verify_ctx, tbs, tbslen) != 1 + || (ret = sm2_verify_finish(&verify_ctx, sig, siglen)) < 0) { + error_print(); + return -1; + } + if (!ret) error_print(); + return ret; +} + +int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen) +{ + int ret; + SM2_KEY public_key; + + if (x509_cert_get_subject_public_key(cacert, cacertlen, &public_key) != 1 + || (ret = x509_cert_verify(a, alen, &public_key, NULL, 0)) < 0) { + error_print(); + return -1; + } + if (!ret) error_print(); + return ret; +} + +int x509_cert_to_pem(const uint8_t *a, size_t alen, FILE *fp) +{ + if (pem_write(fp, "CERTIFICATE", a, alen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp) +{ + if (pem_read(fp, "CERTIFICATE", a, alen, maxlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_from_pem_by_index(uint8_t *a, size_t *alen, size_t maxlen, int index, FILE *fp) +{ + int i; + for (i = 0; i <= index; i++) { + if (x509_cert_from_pem(a, alen, maxlen, fp) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_cert_from_pem_by_subject(uint8_t *a, size_t *alen, size_t maxlen, const uint8_t *name, size_t namelen, FILE *fp) +{ + const uint8_t *d; + size_t dlen; + + for (;;) { + if (x509_cert_from_pem(a, alen, maxlen, fp) != 1) { + error_print(); + return -1; + } + x509_cert_get_subject(a, *alen, &d, &dlen); + + if (dlen == namelen && memcmp(name, d, dlen) == 0) { + return 1; + } + + } + return 0; +} + +int x509_cert_print(FILE *fp, int fmt, int ind, const uint8_t *a, size_t alen) +{ + const uint8_t *d; + size_t dlen; + + if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + x509_certificate_print(fp, fmt, ind, "Certificate", d, dlen); + return 1; +} + +int x509_cert_get_details(const uint8_t *a, size_t alen, + int *version, + const uint8_t **serial_number, size_t *serial_number_len, + int *inner_signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *not_before, time_t *not_after, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **issuer_unique_id, size_t *issuer_unique_id_len, + const uint8_t **subject_unique_id, size_t *subject_unique_id_len, + const uint8_t **extensions, size_t *extensions_len, + int *signature_algor, + const uint8_t **signature, size_t *signature_len) +{ + const uint8_t *d; + size_t dlen; + int sig_alg; + const uint8_t *sig; size_t sig_len; + + int ver; + const uint8_t *serial; size_t serial_len; + int inner_sig_alg; + const uint8_t *isur; size_t isur_len; + time_t before, after; + const uint8_t *subj; size_t subj_len; + SM2_KEY sm2_key; + const uint8_t *isur_uniq_id; size_t isur_uniq_id_len; + const uint8_t *subj_uniq_id; size_t subj_uniq_id_len; + const uint8_t *exts; size_t exts_len; + + if (x509_certificate_from_der(&d, &dlen, &sig_alg, &sig, &sig_len, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + if (x509_explicit_version_from_der(0, &ver, &d, &dlen) < 0 + || asn1_integer_from_der(&serial, &serial_len, &d, &dlen) != 1 + || x509_signature_algor_from_der(&inner_sig_alg, &d, &dlen) != 1 + || asn1_sequence_from_der(&isur, &isur_len, &d, &dlen) != 1 + || x509_validity_from_der(&before, &after, &d, &dlen) != 1 + || asn1_sequence_from_der(&subj, &subj_len, &d, &dlen) != 1 + || x509_public_key_info_from_der(&sm2_key, &d, &dlen) != 1 + || asn1_implicit_bit_octets_from_der(1, &isur_uniq_id, &isur_uniq_id_len, &d, &dlen) < 0 + || asn1_implicit_bit_octets_from_der(2, &subj_uniq_id, &subj_uniq_id_len, &d, &dlen) < 0 + || x509_explicit_exts_from_der(3, &exts, &exts_len, &d, &dlen) < 0) { + error_print(); + return -1; + } + + if (version) *version = ver; + if (serial_number) *serial_number = serial; + if (serial_number_len) *serial_number_len = serial_len; + if (inner_signature_algor) *inner_signature_algor = inner_sig_alg; + if (issuer) *issuer = isur; + if (issuer_len) *issuer_len = isur_len; + if (not_before) *not_before = before; + if (not_after) *not_after = after; + if (subject) *subject = subj; + if (subject_len) *subject_len = subj_len; + if (subject_public_key) *subject_public_key = sm2_key; + if (issuer_unique_id) *issuer_unique_id = isur_uniq_id; + if (issuer_unique_id_len) *issuer_unique_id_len = isur_uniq_id_len; + if (subject_unique_id) *subject_unique_id = subj_uniq_id; + if (subject_unique_id_len) *subject_unique_id_len = subj_uniq_id_len; + if (extensions) *extensions = exts; + if (extensions_len) *extensions_len = exts_len; + if (signature_algor) *signature_algor = sig_alg; + if (signature) *signature = sig; + if (signature_len) *signature_len = sig_len; + return 1; +} + +int x509_cert_get_issuer_and_serial_number(const uint8_t *a, size_t alen, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial_number, size_t *serial_number_len) +{ + return x509_cert_get_details(a, alen, + NULL, // version + serial_number, serial_number_len, // serial + NULL, // signature_algor + issuer, issuer_len, // issuer + NULL, NULL, // validity + NULL, NULL, // subject + NULL, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + NULL, NULL, // extensions + NULL, // signature_algor + NULL, NULL); // signature +} + +int x509_cert_get_subject_public_key(const uint8_t *a, size_t alen, SM2_KEY *public_key) +{ + return x509_cert_get_details(a, alen, + NULL, // version + NULL, NULL, // serial + NULL, // signature_algor + NULL, NULL, // issuer + NULL, NULL, // validity + NULL, NULL, // subject + public_key, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + NULL, NULL, // extensions + NULL, // signature_algor + NULL, NULL); // signature +} + +int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen) +{ + return x509_cert_get_details(a, alen, + NULL, // version + NULL, NULL, // serial + NULL, // signature_algor + NULL, NULL, // issuer + NULL, NULL, // validity + d, dlen, // subject + NULL, // subject_public_key + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id + NULL, NULL, // extensions + NULL, // signature_algor + NULL, NULL); // signature +} + + + +int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp) +{ + const uint8_t *a; + size_t alen; + + while (dlen) { + if (asn1_any_from_der(&a, &alen, &d, &dlen) != 1 + || x509_cert_to_pem(a, alen, fp) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_certs_from_pem(const uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp) +{ + error_print(); + return -1; +} + +int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt) +{ + if (asn1_types_get_count(d, dlen, ASN1_TAG_SEQUENCE, cnt) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen) +{ + error_print(); + return -1; +} + +int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, + const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen) +{ + error_print(); + return -1; +} diff --git a/src/x509_crl.c b/src/x509_crl.c index eb01a803..6bb2b679 100644 --- a/src/x509_crl.c +++ b/src/x509_crl.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,415 +49,535 @@ #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +static const char *x509_crl_reason_names[] = { + "unspecified", + "keyCompromise", + "cACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "notAssigned", + "removeFromCRL", + "privilegeWithdrawn", + "aACompromise", +}; -const char *crl_reason_text(int reason) +static const size_t x509_crl_reason_names_count = + sizeof(x509_crl_reason_names)/sizeof(x509_crl_reason_names[0]); + +const char *x509_crl_reason_name(int reason) { - switch (reason) { - case X509_cr_unspecified: return "unspecified"; - case X509_cr_key_compromise: return "keyCompromise"; - case X509_cr_ca_compromise: return "cACompromise"; - case X509_cr_affiliation_changed: return "affiliationChanged"; - case X509_cr_superseded: return "superseded"; - case X509_cr_cessation_of_operation: return "cessationOfOperation"; - case X509_cr_certificate_hold: return "certificateHold"; - case X509_cr_remove_from_crl: return "removeFromCRL"; - case X509_cr_privilege_withdrawn: return "privilegeWithdrawn"; - case X509_cr_aa_compromise: return "aACompromise"; + if (reason < 0 || reason >= x509_crl_reason_names_count) { + error_print(); + return NULL; } - return NULL; + return x509_crl_reason_names[reason]; } - 84 typedef struct { - 85 uint8_t serial_number[20]; - 86 size_t serial_number_len; - 87 time_t revoke_date; - 88 CRL_EXTENSIONS crlEntryExtensions; - 89 } CRL_REVOKED_CERT; - - -int crl_revoked_cert_to_der(const CRL_REVOKED_CERT *a, uint8_t **out, size_t *outlen) +int x509_crl_reason_from_name(int *reason, const char *name) { + int i; + for (i = 0; i < x509_crl_reason_names_count; i++) { + if (strcmp(name, x509_crl_reason_names[i]) == 0) { + *reason = i; + return 1; + } + } + return 0; +} + +int x509_crl_reason_to_der(int reason, uint8_t **out, size_t *outlen) +{ + if (reason >= 0 && !x509_crl_reason_name(reason)) { + error_print(); + return -1; + } + return asn1_enumerated_to_der(reason, out, outlen); +} + +int x509_crl_reason_from_der(int *reason, const uint8_t **in, size_t *inlen) +{ + return asn1_enumerated_from_der(reason, in, inlen); +} + + +static uint32_t oid_ce_crl_reasons[] = { oid_ce,21 }; +static uint32_t oid_ce_invalidity_date[] = { oid_ce,24 }; +static uint32_t oid_ce_certificate_issuer[] = { oid_ce,29 }; + +static const ASN1_OID_INFO x509_crl_entry_exts[] = { + { OID_ce_crl_reasons, "CRLReasons", oid_ce_crl_reasons, sizeof(oid_ce_crl_reasons)/sizeof(int) }, + { OID_ce_invalidity_date, "InvalidityDate", oid_ce_invalidity_date, sizeof(oid_ce_invalidity_date)/sizeof(int) }, + { OID_ce_certificate_issuer, "CertificateIssuer", oid_ce_certificate_issuer, sizeof(oid_ce_certificate_issuer)/sizeof(int) }, +}; + +static const int x509_crl_entry_exts_count = + sizeof(x509_crl_entry_exts)/sizeof(x509_crl_entry_exts[0]); + +const char *x509_crl_entry_ext_id_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_crl_entry_exts, x509_crl_entry_exts_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_crl_entry_ext_id_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_crl_entry_exts, x509_crl_entry_exts_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_crl_entry_ext_id_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; size_t len = 0; - if (asn1_integer_to_der(a->serial_number, a->serial_number_len, NULL, &len) != 1 - || x509_time_to_der(a->revoke_date, NULL, &len) != 1 - || x509_extension_to_der(a->exts, NULL, &len) != 1 + if (!(info = asn1_oid_info_from_oid(x509_crl_entry_exts, x509_crl_entry_exts_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_integer_to_der(a->serial_number, a->serial_number_len, out, outlen) != 1 - || x509_time_to_der(a->revoke_date, out, outlen) != 1 - || x509_extension_to_der(a->exts, out, outlen) != 1) { + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { error_print(); return -1; } return 1; } -int crl_revoked_cert_from_der(CRL_REVOKED_CERT *a, const uint8_t **in, size_t *inlen) +int x509_crl_entry_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + *oid = 0; + if ((ret = asn1_oid_info_from_der(&info, x509_crl_entry_exts, x509_crl_entry_exts_count, in, inlen)) != 1) { + error_print(); + return -1; + } + *oid = info->oid; + return ret; +} + +int x509_crl_entry_exts_add_reason(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int reason) +{ + int oid = OID_ce_crl_reasons; + size_t curlen = *extslen; + uint8_t val[16]; + uint8_t *p = val; + size_t vlen = 0; + + if (x509_crl_reason_to_der(reason, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_exts_add_invalidity_date(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, time_t tv) +{ + int oid = OID_ce_invalidity_date; + size_t curlen = *extslen; + uint8_t val[16]; + uint8_t *p = val; + size_t vlen = 0; + + if (asn1_generalized_time_to_der(tv, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_exts_add_certificate_issuer(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_certificate_issuer; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_crl_entry_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + error_print(); + return -1; +} + +int x509_revoked_cert_to_der( + const uint8_t *serial, size_t serial_len, + time_t revoke_date, + const uint8_t *entry_exts, size_t entry_exts_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_integer_to_der(serial, serial_len, NULL, &len) != 1 + || asn1_generalized_time_to_der(revoke_date, NULL, &len) != 1 + || asn1_sequence_to_der(entry_exts, entry_exts_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(serial, serial_len, out, outlen) != 1 + || asn1_generalized_time_to_der(revoke_date, out, outlen) != 1 + || asn1_sequence_to_der(entry_exts, entry_exts_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_revoked_cert_from_der( + const uint8_t **serial, size_t *serial_len, + time_t *revoke_date, + const uint8_t **entry_exts, size_t *entry_exts_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_integer_from_der(a->serial_number, &a->serial_number_len, &data, &datalen) != 1 - || x509_time_from_der(&a->revoke_date, &data, &datalen) != 1 - || x509_extensions_from_der(&a->exts, &data, &datalen) != 1 - || datalen) { + if (asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 + || asn1_generalized_time_from_der(revoke_date, &d, &dlen) != 1 + || asn1_sequence_from_der(entry_exts, entry_exts_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } return 1; } -int crl_revoked_cert_print(FILE *fp, const CRL_REVOKED_CERT *a, int format, int indent) -{ - - return 1; -} - -int crl_tbs_cert_list_to_der(const CRL_TBS_CERT_LIST *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (asn1_int_to_der(a->version, NULL, &len) != 1 - || x509_algorithm_id_to_der(a->signature_algor, NULL, &len) != 1 - || x509_name_to_der(&a->issuer, NULL, &len) != 1 - || x509_time_to_der(a->this_update, NULL, &len) != 1 - || x509_time_to_der(a->next_update, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(a->version, out, outlen) != 1 - || x509_algorithm_id_to_der(a->signature_algor, out, outlen) != 1 - || x509_name_to_der(&a->issuer, out, outlen) != 1 - || x509_time_to_der(a->next_update, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int crl_tbs_cert_list_from_der(CRL_TBS_CERT_LIST *a, const uint8_t **in, size_t *inlen) +int x509_revoked_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *p; + size_t len; + time_t tv; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_int_from_der(&a->version, &data, &datalen) != 1 - || x509_algorithm_id_from_der(&a->signature_algor, &data, &datalen) != 1 - || x509_name_from_der(&a->issuer, &data, &datalen) != 1 - || x509_time_from_der(&a->this_update, &data, &datalen) != 1 - || x509_time_from_der(&a->next_update, &data, &datalen) != 1) { - error_print(); - return -1; - } -} - -int x509_cert_list_to_der(const X509_CERT_LIST *a, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (x509_tbs_cert_list_to_der(&a->tbs_cert_list, NULL, &len) != 1 - || x509_signature_algor_to_der(a->signature_algor, NULL, &len) != 1 - || asn1_bit_string_to_der(a->signature, a->signature_len, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_tbs_cert_list_to_der(&a->tbs_cert_list, out, outlen) != 1 - || x509_signature_algor_to_der(a->signature_algor, out, outlen) != 1 - || asn1_bit_string_to_der(a->signature, a->signature_len, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_list_from_der(X509_CERT_LIST *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - const uint8_t *sig; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) - error_print(); - return ret; - } - if (x509_tbs_cert_list_from_der(&a->tbs_cert_list, in, inlen) != 1 - || x509_signature_algor_from_der(&a->signature_algor, in, inlen) != 1 - || asn1_bit_string_from_der(&sig, &a->signature_len, in, inlen) != 1 - || a->signature_len <= 0 - || a->signature_len >= X509_MAX_SIGNATURE_SIZE) { - error_print(); - return -1; - } - - memcpy(a->signature, sig, a->signature_len); + if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "userCertificate", p, len); + if (asn1_generalized_time_from_der(&tv, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "revocationDate: %s\n", ctime(&tv)); + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + //if (ret) x509_crl_entry_exts_print(fp, fmt, ind, "crlEntryExtensions", p, len); // 这里需要一个函数能够处理 + if (asn1_length_is_zero(dlen) != 1) goto err; return 1; +err: + error_print(); + return -1; } -static const int X509_CRLExtensionOIDs[7] = { - OID_id_ce_authorityKeyIdentifier, - OID_id_ce_issuerAltName, - OID_id_ce_cRLNumber, - OID_id_ce_deltaCRLIndicator, - OID_id_ce_issuingDistributionPoint, - OID_id_ce_freshestCRL, - OID_pe_authorityInfoAccess, +static uint32_t oid_ce_authority_key_identifier[] = { oid_ce,35 }; +static uint32_t oid_ce_issuer_alt_name[] = { oid_ce,18 }; +static uint32_t oid_ce_crl_number[] = { oid_ce,20 }; +static uint32_t oid_ce_delta_crl_indicator[] = { oid_ce,27 }; +static uint32_t oid_ce_issuing_distribution_point[] = { oid_ce,28 }; + +static const ASN1_OID_INFO x509_crl_exts[] = { + { OID_ce_authority_key_identifier, "AuthorityKeyIdentifier", oid_ce_authority_key_identifier, sizeof(oid_ce_authority_key_identifier)/sizeof(int) }, + { OID_ce_issuer_alt_name, "IssuerAltName", oid_ce_issuer_alt_name, sizeof(oid_ce_issuer_alt_name)/sizeof(int) }, + { OID_ce_crl_number, "CRLNumber", oid_ce_crl_number, sizeof(oid_ce_crl_number)/sizeof(int) }, + { OID_ce_delta_crl_indicator, "DeltaCRLIndicator", oid_ce_delta_crl_indicator, sizeof(oid_ce_delta_crl_indicator)/sizeof(int) }, + { OID_ce_issuing_distribution_point, "IssuingDistributionPoint", oid_ce_issuing_distribution_point, sizeof(oid_ce_issuing_distribution_point)/sizeof(int) } }; +static const int x509_crl_exts_count = + sizeof(x509_crl_exts)/sizeof(x509_crl_exts[0]); - -void X509_CRLExtensionValue_to_der(const X509_CRLExtensionValue *a, int type, uint8_t **out, size_t *outlen) +const char *x509_crl_ext_id_name(int oid) { - switch (type) { - case OID_id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier_to_der(&a->u.authorityKeyIdentifier, out, outlen); break; - case OID_id_ce_issuerAltName: X509_GeneralNames_to_der(&a->u.issuerAltName, out, outlen); break; - case OID_id_ce_cRLNumber: ASN1_INTEGER_to_der(&a->u.cRLNumber, out, outlen); break; - case OID_id_ce_deltaCRLIndicator: ASN1_INTEGER_to_der(&a->u.deltaCRLIndicator, out, outlen); - case OID_id_ce_issuingDistributionPoint: X509_IssuingDistributionPoint_to_der(&a->u.issuingDistributionPoint, out, outlen); - case OID_id_ce_freshestCRL: X509_CRLDistributionPoints_to_der(&a->u.freshestCRL, out, outlen); - case OID_pe_authorityInfoAccess: X509_AuthorityInfoAccessSyntax_to_der(&a->u.authorityInfoAccess, out, outlen); + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid))) { + error_print(); + return NULL; } + return info->name; } -int X509_CRLExtensionValue_from_der(X509_CRLExtensionValue *a, int type, const uint8_t **in, size_t *inlen) +int x509_crl_ext_id_from_name(const char *name) { - switch (type) { - case OID_id_ce_authorityKeyIdentifier: return AuthorityKeyIdentifier_from_der(&a->u.authorityKeyIdentifier, in, inlen); - case OID_id_ce_issuerAltName: return X509_GeneralNames_from_der(&a->u.issuerAltName, in, inlen); - case OID_id_ce_cRLNumber: return ASN1_INTEGER_from_der(&a->u.cRLNumber, in, inlen); - case OID_id_ce_deltaCRLIndicator: return ASN1_INTEGER_from_der(&a->u.deltaCRLIndicator, in, inlen); - case OID_id_ce_issuingDistributionPoint: return X509_IssuingDistributionPoint_from_der(&a->u.issuingDistributionPoint, in, inlen); - case OID_id_ce_freshestCRL: return X509_CRLDistributionPoints_from_der(&a->u.freshestCRL, in, inlen); - case OID_pe_authorityInfoAccess: return X509_AuthorityInfoAccessSyntax_from_der(&a->u.authorityInfoAccess, in, inlen); + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_crl_exts, x509_crl_exts_count, name))) { + error_print(); + return OID_undef; } + return info->oid; } - - -void X509_CRLExtension_to_der(const X509_CRLExtension *a, uint8_t **out, size_t *outlen) +int x509_crl_ext_id_to_der(int oid, uint8_t **out, size_t *outlen) { - ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen); - ASN1_OBJECT_IDENTIFIER_to_der(&a->extnID, out, outlen); - ASN1_BOOLEAN_to_der(&a->critical, out, outlen); - ASN1_OCTET_STRING_tag_length_to_der(&a->extnValue, out, outlen); - X509_CRLExtensionValue_to_der(&a->extnValue_data, out, outlen); -} - -int X509_CRLExtension_from_der(X509_CRLExtension *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t length; - - if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) { - return ret; - } - data = ((ASN1_SEQUENCE *)a)->data; - length = ((ASN1_SEQUENCE *)a)->length; - if (ASN1_OBJECT_IDENTIFIER_from_der(&a->extnID, &data, &length) <= 0 - || ASN1_BOOLEAN_from_der(&a->critical, &data, &length) < 0 - || ASN1_OCTET_STRING_from_der(&a->extnValue, &data, &length) <= 0 - || length > 0) { + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid))) { + error_print(); return -1; } - data = a->extnValue.data; - length = a->extnValue.length; - if (X509_CRLExtensionValue_from_der(&a->extnValue_data, &data, &length) < 0 - || length > 0) { + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); return -1; } - - return 1; -} - - - - - -void X509_CRLExtensions_add(X509_CRLExtensions *a, const X509_CRLExtension *value) -{ - size_t length = ((ASN1_SEQUENCE *)a)->length; - assert(a->count < 16); - X509_CRLExtension_copy(&a->values[a->count], value); - X509_CRLExtension_to_der(&a->values[a->count], NULL, &length); - ASN1_SEQUENCE_set((ASN1_SEQUENCE *)a, NULL, length); - a->count++; -} - -void X509_CRLExtensions_to_der(const X509_CRLExtensions *a, uint8_t **out, size_t *outlen) -{ - int i; - ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen); - for (i = 0; i < a->count; i++) { - X509_CRLExtension_to_der(&a->value[i], out, outlen); - } -} - -int X509_CRLExtensions_from_der(X509_CRLExtensions *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t length; - - if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) { - return ret; - } - data = ((ASN1_SEQUENCE *)a)->data; - length = ((ASN1_SEQUENCE *)a)->length; - while (length > 0) { - if (a->count >= 16 - || X509_CRLExtension_from_der(&a->values[a->count], &data, &length) <= 0) { - return -1; - } - } return 1; } - - - -// 5.2.5. Issuing Distribution Point -/* --- issuing distribution point extension OID and syntax - -id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } - -IssuingDistributionPoint ::= SEQUENCE { - distributionPoint [0] IMPLICIT DistributionPointName OPTIONAL, - onlyContainsUserCerts [1] IMPLICIT BOOLEAN DEFAULT FALSE, - onlyContainsCACerts [2] IMPLICIT BOOLEAN DEFAULT FALSE, - onlySomeReasons [3] IMPLICIT ReasonFlags OPTIONAL, - indirectCRL [4] IMPLICIT BOOLEAN DEFAULT FALSE, - onlyContainsAttributeCerts [5] IMPLICIT BOOLEAN DEFAULT FALSE } - -- at most one of onlyContainsUserCerts, onlyContainsCACerts, - -- and onlyContainsAttributeCerts may be set to TRUE. -*/ - - - - - - - - - - -void X509_CRLEntryExtension_to_der(const X509_CRLEntryExtension *a, uint8_t **out, size_t *outlen) -{ - ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen); - ASN1_OBJECT_IDENTIFIER_to_der(&a->extnID, out, outlen); - ASN1_BOOLEAN_to_der(&a->critical, out, outlen); - ASN1_OCTET_STRING_tag_length_to_der(&a->extnValue, out, outlen); - X509_CRLEntryExtensionValue_to_der(&a->extnValue_data, out, outlen); -} - -int X509_CRLEntryExtension_from_der(X509_CRLEntryExtension *a, const uint8_t **in, size_t *inlen) +int x509_crl_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t length; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; - if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) { - return ret; - } - data = ((ASN1_SEQUENCE *)a)->data; - length = ((ASN1_SEQUENCE *)a)->length; - if (ASN1_OBJECT_IDENTIFIER_from_der(&a->extnID, &data, &length) <= 0 - || ASN1_BOOLEAN_from_der(&a->critical, &data, &length) < 0 - || ASN1_OCTET_STRING_from_der(&a->extnValue, &data, &length) <= 0 - || length > 0) { + *oid = 0; + if ((ret = asn1_oid_info_from_der(&info, x509_crl_exts, x509_crl_exts_count, in, inlen)) != 1) { + error_print(); return -1; } - data = a->extnValue.data; - length = a->extnValue.length; - if (X509_CRLEntryExtensionValue_from_der(&a->extnValue_data, &data, &length) < 0 - || length > 0) { + *oid = info->oid; + return ret; +} + +int x509_crl_exts_add_authority_key_identifier( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len) +{ + error_print(); + return -1; +} + +int x509_crl_exts_add_issuer_alt_name( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *d, size_t dlen) +{ + error_print(); + return -1; +} + +int x509_crl_exts_add_crl_number( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + int num) +{ + error_print(); + return -1; +} + +int x509_crl_exts_add_delta_crl_indicator( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + int num) +{ + error_print(); + return -1; +} + +int x509_crl_exts_add_issuing_distribution_point( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *dist_point, size_t dist_point_len, + int only_contains_user_certs, + int only_contains_ca_certs, + int only_some_reasons, + int indirect_crl, + int only_contains_attr_certs) +{ + error_print(); + return -1; +} + +int x509_crl_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + error_print(); + return -1; +} + +int x509_tbs_crl_to_der( + int version, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t this_update, time_t next_update, + const uint8_t *revoked_certs, size_t revoked_certs_len, + const uint8_t *exts, size_t exts_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_int_to_der(version, NULL, &len) < 0 + || x509_signature_algor_to_der(signature_algor, NULL, &len) < 0 + || asn1_sequence_to_der(issuer, issuer_len, NULL, &len) != 1 + || x509_time_to_der(this_update, NULL, &len) != 1 + || x509_time_to_der(next_update, NULL, &len) < 0 + || asn1_sequence_to_der(revoked_certs, revoked_certs_len, NULL, &len) < 0 + || asn1_sequence_to_der(exts, exts_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) < 0 + || x509_signature_algor_to_der(signature_algor, out, outlen) < 0 + || asn1_sequence_to_der(issuer, issuer_len, out, outlen) != 1 + || x509_time_to_der(this_update, out, outlen) != 1 + || x509_time_to_der(next_update, out, outlen) < 0 + || asn1_sequence_to_der(revoked_certs, revoked_certs_len, out, outlen) < 0 + || asn1_sequence_to_der(exts, exts_len, out, outlen) < 0) { + error_print(); return -1; } - - return 1; -} - - - - -// CRL Entry Extensions -//*********************************************************************************************************** - -static const int X509_CRLEntryExtensionOIDs[3] = { - OID_id_ce_cRLReasons, - OID_id_ce_invalidityDate, - OID_id_ce_certificateIssuer, -}; - - - -void X509_CRLEntryExtensionValue_to_der(const X509_CRLEntryExtensionValue *a, int type, uint8_t **out, size_t *outlen) -{ - switch (type) { - case OID_id_ce_cRLReasons: ASN1_ENUMERATED_to_der(&a->u.reasonCode, out, outlen); break; - case OID_id_ce_invalidityDate: X509_GeneralizedTime_to_der(&a->u.invalidityDate, out, outlen); break; - case OID_id_ce_certificateIssuer: X509_GeneralNames_to_der(&a->u.certificateIssuer, out, outlen); break; - } -} - -int X509_CRLEntryExtensionValue_from_der(X509_CRLEntryExtensionValue *a, int type, const uint8_t **in, size_t *inlen) -{ - switch (type) { - case OID_id_ce_cRLReasons: return ASN1_ENUMERATED_to_der(&a->u.reasonCode, in, inlen); - case OID_id_ce_invalidityDate: return X509_GeneralizedTime_to_der(&a->u.invalidityDate, in, inlen); - case OID_id_ce_certificateIssuer: return X509_GeneralNames_to_der(&a->u.certificateIssuer, in, inlen); - } -} - -void X509_CRLEntryExtensions_add(X509_CRLEntryExtensions *a, const X509_CRLEntryExtension *value) -{ - size_t length = ((ASN1_SEQUENCE *)a)->length; - assert(a->count < 16); - X509_CRLEntryExtension_copy(&a->values[a->count], value); - X509_CRLEntryExtension_to_der(&a->values[a->count], NULL, &length); - ASN1_SEQUENCE_set((ASN1_SEQUENCE *)a, NULL, length); - a->count++; -} - -void X509_CRLEntryExtensions_to_der(const X509_CRLEntryExtensions *a, uint8_t **out, size_t *outlen) -{ - int i; - ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen); - for (i = 0; i < a->count; i++) { - X509_CRLEntryExtension_to_der(&a->value[i], out, outlen); - } -} - -int X509_CRLEntryExtensions_from_der(X509_CRLExtensions *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t length; - - if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) { - return ret; - } - data = ((ASN1_SEQUENCE *)a)->data; - length = ((ASN1_SEQUENCE *)a)->length; - while (length > 0) { - if (a->count >= 16 - || X509_CRLEntryExtension_from_der(&a->values[a->count], &data, &length) <= 0) { - return -1; - } - } return 1; } +int x509_tbs_crl_from_der( + int *version, + int *signature_algor, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, + time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + const uint8_t **exts, size_t *exts_len, + uint8_t **in, size_t *inlen) +{ + error_print(); + return -1; +} +int x509_tbs_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + error_print(); + return -1; +} +int x509_cert_list_to_der(const uint8_t *tbs_crl, size_t tbs_crl_len, + int signature_algor, const uint8_t *sig, size_t siglen, + uint8_t **out, size_t *outlen) +{ + error_print(); + return -1; +} +int x509_cert_list_from_der(const uint8_t **tbs_crl, size_t *tbs_crl_len, + int *signature_algor, const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen) +{ + error_print(); + return -1; +} +int x509_cert_list_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + error_print(); + return -1; +} +int x509_crl_to_pem(const uint8_t *a, size_t *alen, FILE *fp) +{ + return 1; +} +int x509_crl_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp) +{ + return 1; +} + +int x509_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return 1; +} + +int x509_tbs_crl_sign( + int version, + int signature_algor, + const uint8_t *issuer, size_t issuer_len, + time_t this_update, time_t next_update, + const uint8_t *revoked_certs, size_t revoked_certs_len, + const uint8_t *exts, size_t exts_len, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t *crl, size_t *crl_len) +{ + uint8_t tbs[512]; + size_t tbslen; + SM2_SIGN_CTX sign_ctx; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + uint8_t *p = tbs; + size_t len = 0; + uint8_t *out = crl; + size_t outlen = 0; + + if (x509_tbs_crl_to_der(version, signature_algor, issuer, issuer_len, + this_update, next_update, revoked_certs, revoked_certs_len, + exts, exts_len, &p, &tbslen) != 1) { + error_print(); + return -1; + } + if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 + || sm2_sign_update(&sign_ctx, tbs, tbslen) != 1 + || sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) { + error_print(); + return -1; + } + if (asn1_data_to_der(tbs, tbslen, NULL, &len) != 1 + || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, &out, &outlen) != 1 + || asn1_data_to_der(tbs, tbslen, &out, &outlen) != 1 + || x509_signature_algor_to_der(signature_algor, &out, &outlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, &out, &outlen) != 1) { + error_print(); + return -1; + } + *crl_len = outlen; + return 1; +} + +int x509_crl_verify(const uint8_t *a, size_t alen, + const SM2_KEY *signer_key, const char *signer_id, size_t signer_id_len) +{ + error_print(); + return -1; +} + +int x509_crl_get_details(const uint8_t *crl, size_t crl_len, + int *version, + const uint8_t **issuer, size_t *issuer_len, + time_t *this_update, + time_t *next_update, + const uint8_t **revoked_certs, size_t *revoked_certs_len, + int *signature_algor, + const uint8_t *sig, size_t *siglen) +{ + error_print(); + return -1; +} + +int x509_crl_get_revoked_cert_by_serial_number(const uint8_t *a, size_t alen, + const uint8_t *serial, size_t serial_len, + time_t *revoke_date, + const uint8_t **entry_exts, size_t *entry_exts_len) +{ + return 1; +} diff --git a/src/x509_ext.c b/src/x509_ext.c index 5b48ac94..63b101c3 100644 --- a/src/x509_ext.c +++ b/src/x509_ext.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,854 +56,426 @@ #include #include #include +#include +#include +#include #include -/* -首先应该完成一些重要的证书扩展 +int x509_exts_add_sequence(uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, const uint8_t *d, size_t dlen) +{ + uint8_t val[32 + dlen]; + uint8_t *p = val; + size_t curlen = *extslen; + size_t vlen = 0; + if (asn1_sequence_to_der(d, dlen, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} -BasicConstraints: +int x509_exts_add_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *keyid, size_t keyid_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len) +{ + int oid = OID_ce_authority_key_identifier; + size_t curlen = *extslen; + uint8_t val[512]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; - CA证书必须包含这个扩展(但是如果证书是v1版本的,那么不支持扩展,我们直接不支持V1证书的验证) - 这个扩展中包含depth值,在验证证书链是必须检查depth是否正确 + if (x509_authority_key_identifier_to_der( + keyid, keyid_len, + issuer, issuer_len, + serial, serial_len, + NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_authority_key_identifier_to_der( + keyid, keyid_len, + issuer, issuer_len, + serial, serial_len, + &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} -KeyUsage +int x509_exts_add_subject_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_subject_key_identifier; + size_t curlen = *extslen; + uint8_t val[32 + X509_SUBJECT_KEY_IDENTIFIER_MAX_LEN]; + uint8_t *p = val; + size_t vlen = 0; - CA证书如果包含这个扩展,那么应该设置 CertificateSigner, CRLSigner - SSL终端证书需要这个扩展吗? + if (dlen < X509_SUBJECT_KEY_IDENTIFIER_MIN_LEN + || dlen > X509_SUBJECT_KEY_IDENTIFIER_MAX_LEN) { + error_print(); + return -1; + } + if (asn1_octet_string_to_der(d, dlen, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} -ExtKeyUsage +int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int bits) +{ + int oid = OID_ce_key_usage; + size_t curlen = *extslen; + uint8_t val[16]; + uint8_t *p = val; + size_t vlen = 0; - SSL终端证书应该包含serverAuth, clientAuth - RFC 5480要求这个扩展只能被用于终端证书,但是有些中间CA证书也包含了这个扩展 + if (asn1_bits_to_der(bits, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} -*/ +int x509_exts_add_certificate_policies(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_certificate_policies; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} +int x509_exts_add_policy_mappings(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_policy_mappings; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} -/* -BEGIN SEQUENCE OF +int x509_exts_add_subject_alt_name(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_subject_alt_name; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} - X509_GENERAL_NAMES - X509_POLICY_QUALIFIER_INFOS - X509_CERTIFICATE_POLICIES - X509_POLICY_MAPPINGS - X509_ATTRIBUTES - X509_GENERAL_SUBTREES - X509_CRL_DISTRIBUTION_POINTS +int x509_exts_add_issuer_alt_name(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_issuer_alt_name; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} -这些类型 to_der 还是 implicit to der 都比较简单,只要调用 type_to_der 就可以了 -但是这些类型 from_der 就不一样,必须还要检查输入的长度,如果输入的长度超过了buffer空间,就只能返回错误了 +int x509_exts_add_subject_directory_attributes(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_subject_directory_attributes; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} +int x509_exts_add_name_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *permitted_subtrees, size_t permitted_subtrees_len, + const uint8_t *excluded_subtrees, size_t excluded_subtrees_len) +{ + int oid = OID_ce_name_constraints; + size_t curlen = *extslen; + uint8_t val[512]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; -*/ + if (x509_name_constraints_to_der( + permitted_subtrees, permitted_subtrees_len, + excluded_subtrees, excluded_subtrees_len, + NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_name_constraints_to_der( + permitted_subtrees, permitted_subtrees_len, + excluded_subtrees, excluded_subtrees_len, + &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} +int x509_exts_add_policy_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int require_explicit_policy, int inhibit_policy_mapping) +{ + int oid = OID_ce_policy_constraints; + size_t curlen = *extslen; + uint8_t val[32]; + uint8_t *p = val; + size_t vlen = 0; + if (x509_policy_constraints_to_der( + require_explicit_policy, + inhibit_policy_mapping, + &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} -////////////////////////////////////////////////////////////////////////////////////////// -// x509_[type_name]_[to|from]_der -////////////////////////////////////////////////////////////////////////////////////////// +int x509_exts_add_basic_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int ca, int path_len_constraint) +{ + int oid = OID_ce_basic_constraints; + size_t curlen = *extslen; + uint8_t val[32]; + uint8_t *p = val; + size_t vlen = 0; -/* -int x509_general_names_from_der_ex(int tag, X509_GENERAL_NAMES *a, const uint8_t **in, size_t *inlen) + if (x509_basic_constraints_to_der(ca, path_len_constraint, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const int *key_purposes, size_t key_purposes_cnt) +{ + int oid = OID_ce_ext_key_usage; + size_t curlen = *extslen; + uint8_t val[256]; + uint8_t *p = val; + size_t vlen = 0; + size_t len = 0; + + if (x509_ext_key_usage_to_der(key_purposes, key_purposes_cnt, NULL, &len) != 1 + || asn1_length_le(len, sizeof(val)) != 1 + || x509_ext_key_usage_to_der(key_purposes, key_purposes_cnt, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_crl_distribution_points; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int skip_certs) +{ + int oid = OID_ce_inhibit_any_policy; + size_t curlen = *extslen; + uint8_t val[16]; + uint8_t *p = val; + size_t vlen = 0; + + if (x509_inhibit_any_policy_to_der(skip_certs, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_exts_add_freshest_crl(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const uint8_t *d, size_t dlen) +{ + int oid = OID_ce_freshest_crl; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); +} + +int x509_other_name_to_der( + const uint32_t *type_nodes, size_t type_nodes_cnt, + const uint8_t *value, size_t value_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_object_identifier_to_der(type_nodes, type_nodes_cnt, NULL, &len) != 1 + || asn1_explicit_to_der(0, value, value_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(type_nodes, type_nodes_cnt, out, outlen) != 1 + || asn1_explicit_to_der(0, value, value_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_other_name_from_der( + uint32_t *type_nodes, size_t *type_nodes_cnt, + const uint8_t **value, size_t *value_len, + const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *p; + size_t len; - if ((ret = asn1_constructed_from_der_ex(tag, &data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (datalen > 256) { + if (asn1_object_identifier_from_der(type_nodes, type_nodes_cnt, &p, &len) != 1 + || asn1_explicit_from_der(0, value, value_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { error_print(); return -1; } - memcpy(a->data, data, datalen); - a->datalen = datalen; return 1; } -int x509_general_names_from_der(X509_GENERAL_NAMES *a, const uint8_t **in, size_t *inlen) +int x509_other_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - return x509_general_names_from_der_ex(ASN1_TAG_SEQUENCE, a, in, inlen); -} + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; -int x509_implicit_general_names_from_der(int index, X509_GENERAL_NAMES *a, const uint8_t **in, size_t *inlen) -{ - return x509_general_names_from_der_ex(ASN1_TAG_EXPLICIT(index), a, in, inlen); -} + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; -int x509_certificate_policies_to_der(const X509_CERTIFICATE_POLICIES *a, uint8_t **out, size_t *outlen) -{ - return asn1_sequence_to_der(a->data, a->datalen, out, outlen); -} - -int x509_certificate_policies_from_der(X509_CERTIFICATE_POLICIES *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen > 128) { - error_print(); - return -1; - } - memcpy(a->data, data, datalen); - a->datalen = datalen; + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "type-id", NULL, nodes, nodes_cnt); + if (asn1_explicit_from_der(0, &p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "value", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; return 1; -} - - - - -int x509_policy_qualifier_infos_to_der(const X509_POLICY_QUALIFIER_INFOS *a, uint8_t **out, size_t *outlen) -{ - return asn1_sequence_to_der(a->data, a->datalen, out, outlen); -} - -int x509_policy_qualifier_infos_from_der(X509_POLICY_QUALIFIER_INFOS *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen > 256) { - error_print(); - return -1; - } - memcpy(a->data, data, datalen); - a->datalen = datalen; - return 1; -} - - - - -int x509_certificate_policies_to_der(const X509_CERTIFICATE_POLICIES *a, uint8_t **out, size_t *outlen) -{ - return asn1_sequence_to_der(a->data, a->datalen, out, outlen); -} - -int x509_certificate_policies_from_der(X509_CERTIFICATE_POLICIES *a, const uint8_t **in, size_t *inlen) -{ - int ret - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen > 1024) { - error_print(); - return -1; - } - memcpy(a->data, data, datalen); - a->datalen = datalen; - return 1; -} - -int x509_policy_mappings_to_der(const X509_POLICY_MAPPINGS *a, uint8_t **out, size_t *outlen) -{ - return asn1_sequence_to_der(a->data, a->datalen, out, outlen); -} - -int x509_policy_mappings_from_der(X509_POLICY_MAPPINGS *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen > 1024) { - error_print(); - return -1; - } - memcpy(a->data, data, datalen); - a->datalen = datalen; - return 1; -} - -int x509_attributess_to_der(const X509_ATTRIBUTES *a, uint8_t **out, size_t *outlen) -{ - asn1_sequence_to_der(a->data, a->datalen, out, outlen); - return 1; -} - -int x509_attributes_from_der(X509_ATTRIBUTES *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen > 128) { - error_print(); - return -1; - } - memcpy(a->data, data, datalen); - a->datalen = datalen; - return 1; -} - - -int x509_general_subtrees_to_der(const X509_GENERAL_SUBTREES *a, uint8_t **out, size_t *outlen) -{ - return asn1_sequence_to_der(a->data, a->datalen, out, outlen); -} - -int x509_general_subtrees_from_der(X509_GENERAL_SUBTREES *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen > 128) { - error_print(); - return -1; - } - memcpy(a->data, data, datalen); - a->datalen = datalen; - return 1; -} - - - -*/ - - -static const struct { - uint8_t der; - int oid; - char *name; - char *text; -} x509_kp[] = { - { 1, OID_kp_serverAuth, "serverAuth", "TLS WWW server authentication" }, - { 2, OID_kp_clientAuth, "clientAuth", "TLS WWW client authentication" }, - { 3, OID_kp_codeSigning, "codeSigning", "Signing of downloadable executable code" }, - { 4, OID_kp_emailProtection, "emailProtection", "Email protection" }, - { 8, OID_kp_timeStamping, "timeStamping", "Binding the hash of an object to a time" }, - { 9, OID_kp_OCSPSigning, "OCSPSigning", "Signing OCSP responses" }, -}; - -int x509_key_purpose_from_name(int *oid, const char *name) -{ - int i; - for (i = 0; i < sizeof(x509_kp)/sizeof(x509_kp[0]); i++) { - if (strcmp(name, x509_kp[i].name) == 0) { - *oid = x509_kp[i].oid; - return 1; - } - } +err: error_print(); return -1; } -const char *x509_key_purpose_name(int oid) -{ - int i; - for (i = 0; i < sizeof(x509_kp)/sizeof(x509_kp[0]); i++) { - if (oid == x509_kp[i].oid) { - return x509_kp[i].name; - } - } - return NULL; -} - -const char *x509_key_purpose_text(int oid) -{ - int i; - for (i = 0; i < sizeof(x509_kp)/sizeof(x509_kp[0]); i++) { - if (oid == x509_kp[i].oid) { - return x509_kp[i].text; - } - } - return NULL; -} - -int x509_key_purpose_to_der(int oid, uint8_t **out, size_t *outlen) -{ - uint8_t der[] = { 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x00 }; - int i; - for (i = 0; i < sizeof(x509_kp)/sizeof(x509_kp[0]); i++) { - if (oid == x509_kp[i].oid) { - der[sizeof(der) - 1] = x509_kp[i].der; - if (asn1_type_to_der(ASN1_TAG_OBJECT_IDENTIFIER, der, sizeof(der), out, outlen) != 1) { - error_print(); - return -1; - } - return 1; - } - } - error_print_msg("unknown key purpose oid %d", oid); - return -1; - -} - -int x509_key_purpose_from_der(int *oid, const uint8_t **in, size_t *inlen) -{ - const uint8_t der[] = { 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x00 }; - const uint8_t *data; - size_t datalen; - int ret, i; - - if ((ret = asn1_type_from_der(ASN1_TAG_OBJECT_IDENTIFIER, &data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen != sizeof(der) || memcmp(data, der, sizeof(der)-1) != 0) { - error_print(); - return -1; - } - for (i = 0; i < sizeof(x509_kp)/sizeof(x509_kp[0]); i++) { - if (data[datalen-1] == x509_kp[i].der) { - *oid = x509_kp[i].oid; - return 1; - } - } - // 这种情况下应该把这个值打印出来 - error_puts("unknown ExtKeyUsage OID"); - return -1; -} - -int x509_ext_key_usage_to_der(const int *oids, size_t oids_count, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - size_t i; - for (i = 0; i < oids_count; i++) { - x509_key_purpose_to_der(oids[i], NULL, &len); - } - asn1_sequence_header_to_der(len, out, outlen); - for (i = 0; i < oids_count; i++) { - x509_key_purpose_to_der(oids[i], out, outlen); - } - return 1; -} - -int x509_ext_key_usage_from_der(int *oids, size_t *oids_count, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - *oids_count = 0; - while (datalen) { - if (x509_key_purpose_from_der(oids, &data, &datalen) != 1) { - error_print(); - return -1; - } - oids++; - (*oids_count)++; - } - return 1; -} - - - - -int x509_crl_distribution_points_to_der(const X509_CRL_DISTRIBUTION_POINTS *a, uint8_t **out, size_t *outlen) -{ - return asn1_sequence_to_der(a->data, a->datalen, out, outlen); -} - -int x509_crl_distribution_points_from_der(X509_CRL_DISTRIBUTION_POINTS *a, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *data; - size_t datalen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (datalen > 128) { - error_print(); - return -1; - } - memcpy(a->data, data, datalen); - a->datalen = datalen; - return 1; -} - - - - - - - - - - - -// x509_[type_name]_add_item - -int x509_general_names_add_item(X509_GENERAL_NAMES *a, - int choice, const uint8_t *data, size_t datalen) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_general_name_to_der(choice, data, datalen, &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - -int x509_policy_qualifier_infos_add_item(X509_POLICY_QUALIFIER_INFOS *a, - int oid, const uint8_t *qualifier, size_t qualifier_len) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_policy_qualifier_info_to_der(oid, qualifier, qualifier_len, &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - -int x509_certificate_policies_add_item(X509_CERTIFICATE_POLICIES *a, - int oid, const uint32_t *nodes, size_t nodes_count, - const X509_POLICY_QUALIFIER_INFOS *qualifiers) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_policy_information_to_der(oid, nodes, nodes_count, qualifiers, &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - -int x509_policy_mappings_add_item(X509_POLICY_MAPPINGS *a, - int issuer_policy_oid, const uint32_t *issuer_policy_nodes, size_t issuer_policy_nodes_count, - int subject_policy_oid, const uint32_t *subject_policy_nodes, size_t subject_policy_nodes_count) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_policy_mapping_to_der( - issuer_policy_oid, issuer_policy_nodes, issuer_policy_nodes_count, - subject_policy_oid, subject_policy_nodes, subject_policy_nodes_count, - &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - -int x509_attributes_add_item(X509_ATTRIBUTES *a, - int oid, const uint32_t *nodes, size_t nodes_count, - const uint8_t *values, size_t valueslen) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_attribute_to_der(oid, nodes, nodes_count, values, valueslen, &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - -int x509_general_subtrees_add_item(X509_GENERAL_SUBTREES *a, - int base_choise, const uint8_t *base_data, size_t base_datalen, - int minimum, - int maximum) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_general_subtree_to_der(base_choise, base_data, base_datalen, minimum, maximum, &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - -int x509_crl_distribution_points_add_item(X509_CRL_DISTRIBUTION_POINTS *a, - const X509_DISTRIBUTION_POINT_NAME *dist_point_name, - int reason_bits, - const X509_GENERAL_NAMES *crl_issuer) -{ - uint8_t *p = a->data + a->datalen; - size_t len = 0; - if (x509_distribution_point_to_der(dist_point_name, reason_bits, crl_issuer, &p, &len) != 1) { - error_print(); - return -1; - } - a->datalen += len; - return 1; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// x509_[type_name]_get_next_item -// *next == NULL 表示从头开始 -// 应该吧公共代码提取为一个公共函数 -////////////////////////////////////////////////////////////////////////////////////////// - - -int x509_general_names_get_next_item(const X509_GENERAL_NAMES *a, const uint8_t **next, - int *choice, const uint8_t **data, size_t *datalen) -{ - int ret; - const uint8_t *value; - size_t valuelen; - if ((ret = asn1_sequence_of_get_next_item((ASN1_SEQUENCE_OF *)a, next, &value, &valuelen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - ret = x509_general_name_from_der(choice, data, datalen, &value, &valuelen); - if (ret < 0) error_print(); - return ret; -} - -int x509_policy_qualifier_infos_get_next_item(const X509_POLICY_QUALIFIER_INFOS *a, const uint8_t **next, - int *oid, const uint8_t **qualifier, size_t *qualifier_len) -{ - int ret; - const uint8_t *value; - size_t valuelen; - if ((ret = asn1_sequence_of_get_next_item((ASN1_SEQUENCE_OF *)a, next, &value, &valuelen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - ret = x509_policy_qualifier_info_from_der(oid, qualifier, qualifier_len, &value, &valuelen); - if (ret < 0) error_print(); - return ret; -} - -int x509_certificate_policies_get_next_item(const X509_CERTIFICATE_POLICIES *a, const uint8_t **next, - int *oid, const uint32_t *nodes, size_t *nodes_count, - X509_POLICY_QUALIFIER_INFOS *qualifiers) -{ - int ret; - const uint8_t *value; - size_t valuelen; - /* - if ((ret = asn1_sequence_of_get_next_item((ASN1_SEQUENCE_OF *)a, next, &value, &valuelen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - ret = x509_certificate_policy_from_der(oid, nodes, nodes_count, qualifiers, qualifiers_len, &value, &valuelen); - if (ret < 0) error_print(); - */ - return ret; -} - -int x509_policy_mappings_get_next_item(const X509_POLICY_MAPPINGS *a, const uint8_t **next, - uint32_t *issuer_policy_nodes, size_t *issuer_policy_nodes_count, - uint32_t *subject_policy_nodes, size_t *subject_policy_nodes_count) -{ - int ret; - const uint8_t *value; - size_t valuelen; - if ((ret = asn1_sequence_of_get_next_item((ASN1_SEQUENCE_OF *)a, next, &value, &valuelen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - /* - ret = x509_policy_mapping_from_der( - issuer_policy_nodes, issuer_policy_nodes_count, - subject_policy_nodes, subject_policy_nodes_count, - &value, &valuelen); - */ - if (ret < 0) error_print(); - return ret; -} - -int x509_attributes_get_next_item(const X509_ATTRIBUTES *a, const uint8_t **next, - int *oid, uint32_t *nodes, size_t *nodes_count, - const uint8_t **data, size_t *datalen) -{ - int ret; - const uint8_t *value; - size_t valuelen; - if ((ret = asn1_sequence_of_get_next_item((ASN1_SEQUENCE_OF *)a, next, &value, &valuelen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - ret = x509_attribute_from_der(oid, nodes, nodes_count, data, datalen, &value, &valuelen); - if (ret < 0) error_print(); - return ret; -} - -int x509_general_subtrees_get_next_item(const X509_GENERAL_SUBTREES *a, const uint8_t **next, - int *base_choise, const uint8_t **base_data, size_t *base_datalen, - int *minimum, - int *maximum) -{ - int ret; - const uint8_t *value; - size_t valuelen; - if ((ret = asn1_sequence_of_get_next_item((ASN1_SEQUENCE_OF *)a, next, &value, &valuelen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - ret = x509_general_subtree_from_der( - base_choise, base_data, base_datalen, - minimum, maximum, - &value, &valuelen); - if (ret < 0) error_print(); - return ret; -} - -int x509_crl_distribution_points_get_next_item(const X509_CRL_DISTRIBUTION_POINTS *a, - const uint8_t **next, - X509_DISTRIBUTION_POINT_NAME *distribution_point, - int *reasons, - X509_GENERAL_NAMES *crl_issuer) -{ - int ret; - const uint8_t *value; - size_t valuelen; - if ((ret = asn1_sequence_of_get_next_item((ASN1_SEQUENCE_OF *)a, next, &value, &valuelen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - ret = x509_distribution_point_from_der(distribution_point, reasons, crl_issuer, &value, &valuelen); - if (ret < 0) error_print(); - return ret; -} - -// END SEQUENCE OF - - - -/* - DisplayText CHOICE Universal - Name SEQUENCE OF - OtherName SEQUENCE - EDIPartyName SEQUENCE - GeneralName CHOICE - GeneralNames SEQUENCE OF - AuthorityKeyIdentifier SEQUENCE - CertificatePolicies SEQUENCE OF - PolicyInformation - UserNotice -*/ - -/* -DisplayText ::= CHOICE { IA5String, VisibleString, BMPString, UTF8String } - -*/ -int x509_display_text_to_der(int tag, const char *text, size_t textlen, uint8_t **out, size_t *outlen) -{ - int ret; - switch (tag) { - case ASN1_TAG_IA5String: - case ASN1_TAG_VisibleString: - case ASN1_TAG_UTF8String: - if (strlen(text) != textlen) { - error_print(); - return -1; - } - break; - case ASN1_TAG_BMPString: - break; - default: - error_print(); - return -1; - } - ret = asn1_type_to_der(tag, (const uint8_t *)text, textlen, out, outlen); - if (ret < 0) error_print(); - return ret; -} - -int x509_display_text_from_der(int *tag, const char **text, size_t *textlen, const uint8_t **in, size_t *inlen) -{ - int ret; - - if ((ret = asn1_any_type_from_der(tag, (const uint8_t **)text, textlen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - switch (*tag) { - case ASN1_TAG_IA5String: - case ASN1_TAG_VisibleString: - case ASN1_TAG_UTF8String: - if (strlen(*text) != *textlen) { - error_print(); - return -1; - } - break; - case ASN1_TAG_BMPString: - break; - default: - error_print(); - return -1; - } - return 1; -} - -/* -EDIPartyName ::= SEQUENCE { - nameAssigner [0] EXPLICIT DirectoryString OPTIONAL, - partyName [1] EXPLICIT DirectoryString } - - DirectoryString 是 CHOICE 类型,因此必须为 EXPLICIT Tag -*/ int x509_edi_party_name_to_der( - int assigner_tag, const char *assigner, size_t assigner_len, - int party_name_tag, const char *party_name, size_t party_name_len, + int assigner_choice, const uint8_t *assigner, size_t assigner_len, + int party_name_choice, const uint8_t *party_name, size_t party_name_len, uint8_t **out, size_t *outlen) { - size_t sublen0; - size_t sublen1; size_t len = 0; - if ((assigner && x509_directory_string_to_der(assigner_tag, assigner, assigner_len, NULL, &sublen0) != 1) - || (assigner && asn1_explicit_to_der(0, NULL, sublen0, NULL, &len) != 1) - || x509_directory_string_to_der(party_name_tag, party_name, party_name_len, NULL, &sublen1) != 1 - || asn1_explicit_to_der(1, NULL, sublen1, NULL, &len) != 1 + if (x509_explicit_directory_name_to_der(0, assigner_choice, assigner, assigner_len, NULL, &len) < 0 + || x509_explicit_directory_name_to_der(1, party_name_choice, party_name, party_name_len, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || (assigner && asn1_explicit_header_to_der(0, sublen0, out, outlen) != 1) - || (assigner && x509_directory_string_to_der(assigner_tag, assigner, assigner_len, out, outlen) != 1) - || asn1_explicit_header_to_der(1, sublen1, out, outlen) != 1 - || x509_directory_string_to_der(party_name_tag, party_name, party_name_len, out, outlen) != 1) { + || x509_explicit_directory_name_to_der(0, assigner_choice, assigner, assigner_len, out, outlen) < 0 + || x509_explicit_directory_name_to_der(1, party_name_choice, party_name, party_name_len, out, outlen) != 1) { error_print(); return -1; } return 1; } -int x509_edi_party_name_from_der(int *assigner_tag, const char **assigner, size_t *assigner_len, - int *party_name_tag, const char **party_name, size_t *party_name_len, +int x509_edi_party_name_from_der( + int *assigner_choice, const uint8_t **assigner, size_t *assigner_len, + int *party_name_choice, const uint8_t **party_name, size_t *party_name_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data, *subdata0; - size_t datalen; - const uint8_t *exp0, *exp1; - size_t explen0, explen1; + const uint8_t *p; + size_t len; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_explicit_from_der(0, &exp0, &explen0, &data, &datalen) < 0 - || asn1_explicit_from_der(1, &exp1, &explen1, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - if ((exp0 && x509_directory_string_from_der(assigner_tag, assigner, assigner_len, &exp0, &explen0) != 1) - || x509_directory_string_from_der(party_name_tag, party_name, party_name_len, &exp1, &explen1) != 1) { + if (x509_explicit_directory_name_from_der(0, assigner_choice, assigner, assigner_len, &p, &len) < 0 + || x509_explicit_directory_name_from_der(1, party_name_choice, party_name, party_name_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { error_print(); return -1; } + return 1; +} + +int x509_edi_party_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + int tag; + + if ((ret = x509_explicit_directory_name_from_der(0, &tag, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_directory_name_print(fp, fmt, ind, "nameAssigner", tag, p, len); + if (x509_explicit_directory_name_from_der(1, &tag, &p, &len, &d, &dlen) != 1) goto err; + x509_directory_name_print(fp, fmt, ind, "partyName", tag, p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); return -1; } -/* -OtherName ::= SEQUENCE { - type-id OBJECT IDENTIFIER, - value [0] EXPLICIT ANY DEFINED BY type-id -} -*/ -int x509_other_name_to_der(int oid, const uint32_t *nodes, size_t nodes_count, - const uint8_t *value, size_t valuelen, - uint8_t **out, size_t *outlen) +// GeneralName CHOICE 中有的是基本类型,有的是SEQUENCE,在设置标签时是否有区别? +// 这里是否支持OPTIONAL?? +int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) { - size_t len = 0; - if (asn1_object_identifier_to_der(oid, nodes, nodes_count, NULL, &len) != 1 - || asn1_explicit_to_der(0, value, valuelen, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(oid, nodes, nodes_count, out, outlen) != 1 - || asn1_explicit_to_der(0, value, valuelen, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; + return asn1_implicit_to_der(choice, d, dlen, out, outlen); } -int x509_other_name_from_der(int *oid, uint32_t *nodes, size_t *nodes_count, - const uint8_t **value, size_t *valuelen, const uint8_t **in, size_t *inlen) +int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) { - int ret; - const uint8_t *data; - size_t datalen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + int ret, tag; + if ((ret = asn1_any_type_from_der(&tag, d, dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(oid, nodes, nodes_count, &data, &datalen) != 1 - || asn1_explicit_from_der(0, value, valuelen, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; + + return -1; } -/* -GeneralName ::= CHOICE { - otherName [0] IMPLICIT OtherName, - rfc822Name [1] IMPLICIT IA5String, - dNSName [2] IMPLICIT IA5String, - x400Address [3] IMPLICIT ORAddress, - directoryName [4] IMPLICIT Name, - ediPartyName [5] IMPLICIT EDIPartyName, - uniformResourceIdentifier [6] IMPLICIT IA5String, - iPAddress [7] IMPLICIT OCTET STRING, - registeredID [8] IMPLICIT OBJECT IDENTIFIER } - - 这个类型非常讨厌,IMPLICT类型导致影响了的Tag,看来所有的类型都需要为Tag的修改做准备 - - 当 choice 为基本类型时,输入为类型的值数据 - 当 choice 为 SEQUENCE 时,输入为该 SEQUENCE 的TLV DER编码 - - 由于X509_NAME是一个存储类型,因此也污染了这个CHOICE -*/ -int x509_general_name_to_der(int choice, const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) +int x509_general_name_print(FILE *fp, int fmt, int ind, const char *label, int choice, const uint8_t *d, size_t dlen) { - uint8_t *tag = *out; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + switch (choice) { - case X509_gn_rfc822Name: - case X509_gn_dnsName: - case X509_gn_uniformResourceIdentifier: - if (strlen((char *)data) != datalen) { + case 0: return x509_other_name_print(fp, fmt, ind, "otherName", d, dlen); + case 1: return asn1_string_print(fp, fmt, ind, "rfc822Name", ASN1_TAG_IA5String, d, dlen); + case 2: return asn1_string_print(fp, fmt, ind, "DNSName", ASN1_TAG_IA5String, d, dlen); + case 3: return format_bytes(fp, fmt, ind, "x400Address", d, dlen); + case 4: return x509_name_print(fp, fmt, ind, "directoryName", d, dlen); + case 5: return x509_edi_party_name_print(fp, fmt, ind, "ediPartyName", d, dlen); + case 6: return asn1_string_print(fp, fmt, ind, "URI", ASN1_TAG_IA5String, d, dlen); + case 7: return format_bytes(fp, fmt, ind, "IPAddress", d, dlen); + case 8: + { + uint32_t nodes[32]; + size_t nodes_cnt; + if (asn1_object_identifier_from_octets(nodes, &nodes_cnt, d, dlen) != 1) { error_print(); return -1; } - case X509_gn_ipAddress: - asn1_type_to_der(ASN1_TAG_IMPLICIT(choice), data, datalen, out, outlen); - break; - - case X509_gn_otherName: - case X509_gn_x400Address: - case X509_gn_directoryName: - case X509_gn_ediPartyName: - case X509_gn_registeredID: - asn1_data_to_der(data, datalen, out, outlen); - *tag = ASN1_TAG_IMPLICIT(choice); - break; - + return asn1_object_identifier_print(fp, fmt, ind, "registeredID", NULL, nodes, nodes_cnt); + } default: error_print(); return -1; @@ -911,455 +483,425 @@ int x509_general_name_to_der(int choice, const uint8_t *data, size_t datalen, ui return 1; } -int x509_general_name_from_der(int *choice, const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) +int x509_general_names_add_general_name(uint8_t *gns, size_t *gnslen, size_t maxlen, + int choice, const uint8_t *d, size_t dlen) { + error_print(); return -1; } +int x509_general_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int choice; + const uint8_t *p; + size_t len; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; - - - - + while (dlen) { + if (x509_general_name_from_der(&choice, &p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_general_name_print(fp, fmt, ind, "GeneralName", choice, p, len); + } + return 1; +} int x509_authority_key_identifier_to_der( const uint8_t *keyid, size_t keyid_len, - const X509_GENERAL_NAMES *issuer, - const uint8_t *serial_number, size_t serial_number_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, uint8_t **out, size_t *outlen) { size_t len = 0; - - asn1_implicit_octet_string_to_der(0, keyid, keyid_len, NULL, &len); - x509_implicit_general_names_to_der(1, issuer, NULL, &len); - asn1_implicit_integer_to_der(2, serial_number, serial_number_len, NULL, &len); - asn1_sequence_header_to_der(len, out, outlen); - asn1_implicit_octet_string_to_der(0, keyid, keyid_len, out, outlen); - x509_implicit_general_names_to_der(1, issuer, out, outlen); - asn1_implicit_integer_to_der(2, serial_number, serial_number_len, out, outlen); + if (asn1_implicit_octet_string_to_der(0, keyid, keyid_len, NULL, &len) < 0 + || asn1_implicit_sequence_to_der(1, issuer, issuer_len, NULL, &len) < 0 + || asn1_implicit_integer_to_der(2, serial, serial_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_implicit_octet_string_to_der(0, keyid, keyid_len, out, outlen) < 0 + || asn1_implicit_sequence_to_der(1, issuer, issuer_len, out, outlen) < 0 + || asn1_implicit_integer_to_der(2, serial, serial_len, out, outlen) < 0) { + error_print(); + return -1; + } return 1; } int x509_authority_key_identifier_from_der( const uint8_t **keyid, size_t *keyid_len, - X509_GENERAL_NAMES *issuer, - const uint8_t **serial_number, size_t *serial_number_len, + const uint8_t **issuer, size_t *issuer_len, + const uint8_t **serial, size_t *serial_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *d; + size_t dlen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - - if (asn1_implicit_octet_string_from_der(0, keyid, keyid_len, in, inlen) < 0 - || x509_implicit_general_names_from_der(1, issuer, in, inlen) < 0 - || asn1_implicit_integer_from_der(2, serial_number, serial_number_len, in, inlen) < 0 - || datalen > 0) { + if (asn1_implicit_octet_string_from_der(0, keyid, keyid_len, &d, &dlen) < 0 + || asn1_implicit_sequence_from_der(1, issuer, issuer_len, &d, &dlen) < 0 + || asn1_implicit_integer_from_der(2, serial, serial_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } return 1; } -int x509_authority_key_identifier_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) +int x509_authority_key_identifier_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { int ret; const uint8_t *p; size_t len; - const uint8_t *keyid; - size_t keyidlen; - X509_GENERAL_NAMES issuer; - const uint8_t *serial; - size_t seriallen; - if (asn1_sequence_from_der(&p, &len, &data, &datalen) != 1 - || datalen) { - error_print(); - return -1; - } - if ((ret = asn1_implicit_octet_string_from_der(0, &keyid, &keyidlen, &p, &len)) < 0) { - error_print(); - return -1; - } else if (ret) { - format_bytes(fp, format, indent, "KeyIdentifier : ", keyid, keyidlen); - } - if ((ret = x509_implicit_general_names_from_der(1, &issuer, &p, &len)) < 0) { - error_print(); - return -1; - } else if (ret) { - format_print(fp, format, indent, "AuthorityCertIssuer\n"); - //x509_general_names_print(fp, &issuer, format, indent + 4); - } - if ((ret = asn1_implicit_integer_from_der(2, &serial, &seriallen, &p, &len)) < 0) { - error_print(); - return -1; - } else if (ret) { - format_bytes(fp, format, indent, "AuthorityCertSerialNumber : ", serial, seriallen); - } - if (len) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_implicit_octet_string_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "keyIdentifier", p, len); + if ((ret = asn1_implicit_sequence_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_names_print(fp, fmt, ind, "authorityCertIssuer", p, len); + if ((ret = asn1_implicit_integer_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) format_bytes(fp, fmt, ind, "authorityCertSerialNumber", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +static const char *x509_key_usages[] = { + "digitalSignature", + "nonRepudiation", + "keyEncipherment", + "dataEncipherment", + "keyAgreement", + "keyCertSign", + "cRLSign", + "encipherOnly", + "decipherOnly", +}; + +static size_t x509_key_usages_count = + sizeof(x509_key_usages)/sizeof(x509_key_usages[0]); + +int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, int bits) +{ + return asn1_bits_print(fp, fmt, ind, label, x509_key_usages, x509_key_usages_count, bits); +} + +int x509_notice_reference_to_der( + int org_tag, const uint8_t *org, size_t org_len, + const int *notice_numbers, size_t notice_numbers_cnt, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_display_text_to_der(org_tag, org, org_len, NULL, &len) != 1 + || asn1_sequence_of_int_to_der(notice_numbers, notice_numbers_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_display_text_to_der(org_tag, org, org_len, out, outlen) != 1 + || asn1_sequence_of_int_to_der(notice_numbers, notice_numbers_cnt, out, outlen) != 1) { error_print(); return -1; } return 1; } - - - - - - - - - - - - -/* -3 -KeyUsage ::= BIT STRING { - digitalSignature (0), - nonRepudiation (1), -- recent editions of X.509 have - -- renamed this bit to contentCommitment - keyEncipherment (2), - dataEncipherment (3), - keyAgreement (4), - keyCertSign (5), - cRLSign (6), - encipherOnly (7), - decipherOnly (8) } -*/ - - - - -/* -4 -CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation - -PolicyInformation ::= SEQUENCE { - policyIdentifier OBJECT IDENTIFIER, - policyQualifiers SEQUENCE SIZE (1..MAX) OF - PolicyQualifierInfo OPTIONAL } - -PolicyQualifierInfo ::= SEQUENCE { - policyQualifierId OBJECT IDENTIFIER, - qualifier ANY DEFINED BY policyQualifierId } - -Qualifier ::= CHOICE { - cPSuri IA5String, - userNotice UserNotice } - -UserNotice ::= SEQUENCE { - noticeRef NoticeReference OPTIONAL, - explicitText DisplayText OPTIONAL } - -NoticeReference ::= SEQUENCE { - organization DisplayText, - noticeNumbers SEQUENCE OF INTEGER } - - -看来这是一个非常复杂的扩展,可能很难通过简单的接口去设置。 -我应该把这个设为一个独立的对象,在设置的时候,直接提供这个对象的DER -在解析的时候,可以有独立的函数将其解析成文本之类的可能更好 - -虽然这个扩展很复杂,但是我们的主要需求就是能够解析并转化为可显示的字符串 - -这个扩展在证书中确实是出现的,但是我们主要的目标还是显示这个扩展的内容 - -*/ - - - - - - - - - - - - - - - -/* -NoticeReference ::= SEQUENCE { - organization DisplayText, - noticeNumbers SEQUENCE OF INTEGER -} -*/ -int x509_notice_reference_to_der( - int organization_tag, const char *organization, size_t organization_len, - const int *notice_numbers, size_t notice_numbers_count, - uint8_t **out, size_t *outlen) -{ - size_t sublen, len; - size_t i; - - x509_display_text_to_der(organization_tag, organization, organization_len, NULL, &len); - for (i = 0; i < notice_numbers_count; i++) { - asn1_int_to_der(notice_numbers[i], NULL, &len); - } - asn1_sequence_to_der(NULL, sublen, NULL, &len); - - asn1_sequence_header_to_der(len, out, outlen); - x509_display_text_to_der(organization_tag, organization, organization_len, out, outlen); - asn1_sequence_header_to_der(sublen, out, outlen); - for (i = 0; i < notice_numbers_count; i++) { - asn1_int_to_der(notice_numbers[i], out, outlen); - } - return -1; -} - int x509_notice_reference_from_der( - int *organization_tag, const char **organization, size_t *organization_len, - int *notice_numbers, size_t *notice_numbers_count, + int *org_tag, const uint8_t **org, size_t *org_len, + int notice_numbers[X509_MAX_NOTICE_NUMBERS], size_t *notice_numbers_cnt, size_t max_notice_numbers, //FIXME: max_notice_numbers 还没检查 const uint8_t **in, size_t *inlen) { - const uint8_t *data, *subdata; - size_t datalen = 0, subdatalen = 0; int ret; + const uint8_t *d; + size_t dlen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - - if (x509_display_text_from_der(organization_tag, organization, organization_len, &data, &datalen) != 1 - || asn1_sequence_from_der(&subdata, &subdatalen, &data, &datalen) != 1 - || datalen > 0 - || subdatalen <= 0) { + if (x509_display_text_from_der(org_tag, org, org_len, &d, &dlen) != 1 + || asn1_sequence_of_int_from_der(notice_numbers, notice_numbers_cnt, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } - - *notice_numbers_count = 0; - while (subdatalen) { - if (asn1_int_from_der(notice_numbers, &subdata, &subdatalen) != 1) { - error_print(); - return -1; - } - (*notice_numbers_count)++; - } - - return 1; + return -1; } +int x509_notice_reference_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int tag; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_display_text_from_der(&tag, &p, &len, &d, &dlen) != 1) goto err; + x509_display_text_print(fp, fmt, ind, "organization", tag, p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + asn1_sequence_of_int_print(fp, fmt, ind, "noticeNumbers", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} -/* -UserNotice ::= SEQUENCE { - noticeRef NoticeReference OPTIONAL, - explicitText DisplayText OPTIONAL } -*/ int x509_user_notice_to_der( - const uint8_t *notice_ref_der, size_t notice_ref_der_len, - int explicit_text_tag, const char *explicit_text, size_t explicit_text_len, + int notice_ref_org_tag, const uint8_t *notice_ref_org, size_t notice_ref_org_len, + const int *notice_ref_notice_numbers, size_t notice_ref_notice_numbers_cnt, + int explicit_text_tag, const uint8_t *explicit_text, size_t explicit_text_len, uint8_t **out, size_t *outlen) { size_t len = 0; - asn1_data_to_der(notice_ref_der, notice_ref_der_len, NULL, &len); - x509_display_text_to_der(explicit_text_tag, explicit_text, explicit_text_len, NULL, &len); - - asn1_sequence_header_to_der(len, out, outlen); - asn1_data_to_der(notice_ref_der, notice_ref_der_len, out, outlen); - x509_display_text_to_der(explicit_text_tag, explicit_text, explicit_text_len, out, outlen); - - return -1; + if (x509_notice_reference_to_der( + notice_ref_org_tag, notice_ref_org, notice_ref_org_len, + notice_ref_notice_numbers, notice_ref_notice_numbers_cnt, + NULL, &len) < 0 + || x509_display_text_to_der(explicit_text_tag, explicit_text, explicit_text_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_notice_reference_to_der( + notice_ref_org_tag, notice_ref_org, notice_ref_org_len, + notice_ref_notice_numbers, notice_ref_notice_numbers_cnt, + out, outlen) < 0 + || x509_display_text_to_der(explicit_text_tag, explicit_text, explicit_text_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; } int x509_user_notice_from_der( - const uint8_t **notice_ref_der, size_t *notice_ref_der_len, - int *explicit_text_tag, const char **explicit_text, size_t *explicit_text_len, + int *notice_ref_org_tag, const uint8_t **notice_ref_org, size_t *notice_ref_org_len, + int *notice_ref_notice_numbers, size_t *notice_ref_notice_numbers_cnt, size_t max_notice_ref_notice_numbers, // FIXME: max_notice_ref_notice_numbers + int *explicit_text_tag, const uint8_t **explicit_text, size_t *explicit_text_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; - const uint8_t *subdata; - size_t subdatalen; + const uint8_t *d; + size_t dlen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } + if (x509_notice_reference_from_der(notice_ref_org_tag, notice_ref_org, notice_ref_org_len, + notice_ref_notice_numbers, notice_ref_notice_numbers_cnt, max_notice_ref_notice_numbers, &d, &dlen) < 0 + || x509_display_text_from_der(explicit_text_tag, explicit_text, explicit_text_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} - *notice_ref_der = data; - asn1_sequence_from_der(&subdata, &subdatalen, &data, &datalen); - *notice_ref_der_len = data - (*notice_ref_der); - x509_display_text_from_der(explicit_text_tag, explicit_text, explicit_text_len, in, inlen); +int x509_user_notice_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + int tag; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_notice_reference_print(fp, fmt, ind, "noticeRef", p, len); + if ((ret = x509_display_text_from_der(&tag, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_display_text_print(fp, fmt, ind, "explicitText", tag, p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); return -1; } - -/* -PolicyQualifierInfo ::= SEQUENCE { - policyQualifierId OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ), - qualifier ANY DEFINED BY policyQualifierId } - -当policyQualifierId == id-qt-cps 时,qualifier为CPSuri,否则为UserNotice - - Qualifier ::= CHOICE { - cPSuri IA5String, - userNotice UserNotice } - -*/ -int x509_policy_qualifier_info_to_der(int oid, - const uint8_t *qualifier, size_t qualifier_len, uint8_t **out, size_t *outlen) +int x509_policy_qualifier_info_to_der( + int oid, + const uint8_t *qualifier, size_t qualifier_len, + uint8_t **out, size_t *outlen) { size_t len = 0; - asn1_object_identifier_to_der(oid, NULL, 0, NULL, &len); - switch (oid) { - case OID_qt_cps: - asn1_ia5_string_to_der((char *)qualifier, NULL, &len); - break; - case OID_qt_unotice: - asn1_data_to_der(qualifier, qualifier_len, NULL, &len); - break; + if (x509_qualifier_id_to_der(oid, NULL, &len) != 1 + || asn1_any_to_der(qualifier, qualifier_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_qualifier_id_to_der(oid, out, outlen) != 1 + || asn1_any_to_der(qualifier, qualifier_len, out, outlen) != 1) { + error_print(); + return -1; } - - asn1_sequence_header_to_der(len, out, outlen); - asn1_object_identifier_to_der(oid, NULL, 0, out, outlen); - switch (oid) { - case OID_qt_cps: - asn1_ia5_string_to_der((char *)qualifier, out, &len); - break; - case OID_qt_unotice: - asn1_data_to_der(qualifier, qualifier_len, out, &len); - break; - } - return 1; } int x509_policy_qualifier_info_from_der(int *oid, const uint8_t **qualifier, size_t *qualifier_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; - uint32_t nodes[16]; - size_t nodes_count; + const uint8_t *p; + size_t len; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(oid, nodes, &nodes_count, &data, &datalen) != 1) { + if (x509_qualifier_id_from_der(oid, &p, &len) != 1 + || asn1_any_from_der(qualifier, qualifier_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { error_print(); return -1; } + return 1; +} - switch (*oid) { +int x509_policy_qualifier_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + const uint8_t *p; + size_t len; + + if (x509_qualifier_id_from_der(&oid, &d, &dlen) != 1) goto err; + switch (oid) { case OID_qt_cps: - asn1_ia5_string_from_der((const char **)qualifier, qualifier_len, &data, &datalen); + if (asn1_ia5_string_from_der((const char **)&p, &len, &d, &dlen) != 1) goto err; + format_string(fp, fmt, ind, "cPSuri", p, len); break; case OID_qt_unotice: - *qualifier_len = datalen; - asn1_data_from_der(qualifier, *qualifier_len, &data, &datalen); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_user_notice_print(fp, fmt, ind, "userNotice", p, len); break; } - + return 1; +err: + error_print(); return -1; } -/* -PolicyInformation ::= SEQUENCE { - policyIdentifier OBJECT IDENTIFIER, - -- 由CA定义的,RFC 5280中仅规定为一个可选的OID anyPolicy - policyQualifiers SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo OPTIONAL - -- 必须为这个准备一个独立的类型 +int x509_policy_qualifier_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_policy_qualifier_info_print(fp, fmt, ind, "PolicyQualifierInfo", p, len); + } + return 1; } -*/ int x509_policy_information_to_der( - int oid, const uint32_t *nodes, size_t nodes_count, - const X509_POLICY_QUALIFIER_INFOS *qualifiers, + int oid, const uint32_t *nodes, size_t nodes_cnt, + const uint8_t *qualifiers, size_t qualifiers_len, uint8_t **out, size_t *outlen) { size_t len = 0; - asn1_object_identifier_to_der(oid, nodes, nodes_count, NULL, &len); - x509_policy_qualifier_infos_to_der(qualifiers, NULL, &len); - asn1_sequence_header_to_der(len, out, outlen); - asn1_object_identifier_to_der(oid, nodes, nodes_count, out, outlen); - x509_policy_qualifier_infos_to_der(qualifiers, out, outlen); - + if (x509_cert_policy_id_to_der(oid, nodes, nodes_cnt, NULL, &len) != 1 + || asn1_sequence_to_der(qualifiers, qualifiers_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_cert_policy_id_to_der(oid, nodes, nodes_cnt, out, outlen) != 1 + || asn1_sequence_to_der(qualifiers, qualifiers_len, out, outlen) < 0) { + error_print(); + return -1; + } return 1; } int x509_policy_information_from_der( - int *oid, uint32_t *nodes, size_t *nodes_count, - X509_POLICY_QUALIFIER_INFOS *qualifiers, + int *oid, uint32_t *nodes, size_t *nodes_cnt, + const uint8_t **qualifiers, size_t *qualifiers_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *d; + size_t dlen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(oid, nodes, nodes_count, &data, &datalen) != 1 - || x509_policy_qualifier_infos_from_der(qualifiers, &data, &datalen) != 1 - || datalen > 0) { + if (x509_cert_policy_id_from_der(oid, nodes, nodes_cnt, &d, &dlen) != 1 + || asn1_sequence_from_der(qualifiers, qualifiers_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } return 1; } +int x509_policy_information_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, oid; + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; -/* -CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation -*/ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + if (x509_cert_policy_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "policyIdentifier", x509_cert_policy_id_name(oid), nodes, nodes_cnt); + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_policy_qualifier_infos_print(fp, fmt, ind, "policyQualifiers", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} +int x509_certificate_policies_add_policy_information(uint8_t *d, size_t *dlen, size_t maxlen, + int policy_oid, const uint32_t *policy_nodes, size_t policy_nodes_cnt, + const uint8_t *qualifiers, size_t qualifiers_len) +{ + error_print(); + return -1; +} +int x509_certificate_policies_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; - - -// 这个扩展的数据是一个SEQUENCE OF SEQUENCE,应该统一考虑一下如何处理SEQUENCE OF 这样的返回值 -// 一种是提供一个数组,每个数组是一个SEQUENCE -// 还是只返回这个SEQUENCE OF的数据? - - -/* -5 - -PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { - issuerDomainPolicy CertPolicyId, - subjectDomainPolicy CertPolicyId } - -CertPolicyId ::= OBJECT IDENTIFIER - -This extension MAY be supported by CAs and/or applications. - Conforming CAs SHOULD mark this extension as critical. - -这个也是SEQUENCE OF SEQUENCE -在设置的时候给出数组实际上不太方便 -*/ - - + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_policy_information_print(fp, fmt, ind, label, p, len); + } + return 1; +} int x509_policy_mapping_to_der( - int issuer_policy_oid, const uint32_t *issuer_policy_nodes, size_t issuer_policy_nodes_count, - int subject_policy_oid, const uint32_t *subject_policy_nodes, size_t subject_policy_nodes_count, + int issuer_policy_oid, const uint32_t *issuer_policy_nodes, size_t issuer_policy_nodes_cnt, + int subject_policy_oid, const uint32_t *subject_policy_nodes, size_t subject_policy_nodes_cnt, uint8_t **out, size_t *outlen) { size_t len = 0; - if (asn1_object_identifier_to_der(issuer_policy_oid, issuer_policy_nodes, issuer_policy_nodes_count, NULL, &len) != 1 - || asn1_object_identifier_to_der(subject_policy_oid, subject_policy_nodes, subject_policy_nodes_count, NULL, &len) != 1 + if (x509_cert_policy_id_to_der(issuer_policy_oid, + issuer_policy_nodes, issuer_policy_nodes_cnt, NULL, &len) != 1 + || x509_cert_policy_id_to_der(subject_policy_oid, + subject_policy_nodes, subject_policy_nodes_cnt, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_object_identifier_to_der(issuer_policy_oid, issuer_policy_nodes, issuer_policy_nodes_count, out, outlen) != 1 - || asn1_object_identifier_to_der(subject_policy_oid, subject_policy_nodes, subject_policy_nodes_count, out, outlen) != 1) { + || x509_cert_policy_id_to_der(issuer_policy_oid, + issuer_policy_nodes, issuer_policy_nodes_cnt, out, outlen) != 1 + || x509_cert_policy_id_to_der(subject_policy_oid, + subject_policy_nodes, subject_policy_nodes_cnt, out, outlen) != 1) { error_print(); return -1; } @@ -1367,1251 +909,665 @@ int x509_policy_mapping_to_der( } int x509_policy_mapping_from_der( - int *issuer_policy_oid, uint32_t *issuer_policy_nodes, size_t *issuer_policy_nodes_count, - int *subject_policy_oid, uint32_t *subject_policy_nodes, size_t *subject_policy_nodes_count, + int *issuer_policy_oid, uint32_t *issuer_policy_nodes, size_t *issuer_policy_nodes_cnt, + int *subject_policy_oid, uint32_t *subject_policy_nodes, size_t *subject_policy_nodes_cnt, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(issuer_policy_oid, issuer_policy_nodes, issuer_policy_nodes_count, &data, &datalen) != 1 - || asn1_object_identifier_from_der(subject_policy_oid, subject_policy_nodes, subject_policy_nodes_count, &data, &datalen) != 1 - || datalen > 0) { + if (x509_cert_policy_id_from_der(issuer_policy_oid, + issuer_policy_nodes, issuer_policy_nodes_cnt, &d, &dlen) != 1 + || x509_cert_policy_id_from_der(subject_policy_oid, + subject_policy_nodes, subject_policy_nodes_cnt, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } return 1; } +int x509_policy_mapping_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + uint32_t nodes[32]; + size_t nodes_cnt; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; -/* -## 6 - -SubjectAltName ::= GeneralNames - -GeneralNames 也是 SEQUENCE OF SEQUENCE - -提供证书主体的多个可替代的名字,如域名、IP地址、邮件地址等。 - - - -*/ - - - -/* -7 -IssuerAltName ::= GeneralNames -*/ - - - - -/* -8 -SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute - -Attribute ::= SEQUENCE { - type OBJECT IDENTIFIER, - values SET OF AttributeValue - -- values的类型是SET OF ! + if (x509_cert_policy_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "issuerDomainPolicy", x509_cert_policy_id_name(oid), nodes, nodes_cnt); + if (x509_cert_policy_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "subjectDomainPolicy", x509_cert_policy_id_name(oid), nodes, nodes_cnt); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; } -AttributeValue ::= ANY -*/ + +int x509_policy_mappings_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_policy_mapping_print(fp, fmt, ind, label, p, len); + } + return 1; +} + int x509_attribute_to_der( - int oid, const uint32_t *nodes, size_t nodes_count, - const uint8_t *values, size_t valueslen, + const uint32_t *nodes, size_t nodes_cnt, + const uint8_t *values, size_t values_len, uint8_t **out, size_t *outlen) { size_t len = 0; - - asn1_object_identifier_to_der(oid, nodes, nodes_count, NULL, &len); - asn1_set_to_der(values, valueslen, NULL, &len); - asn1_sequence_header_to_der(len, out, outlen); - asn1_object_identifier_to_der(oid, nodes, nodes_count, out, outlen); - asn1_set_to_der(values, valueslen, out, outlen); + if (asn1_object_identifier_to_der(nodes, nodes_cnt, NULL, &len) != 1 + || asn1_set_to_der(values, values_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(nodes, nodes_cnt, out, outlen) != 1 + || asn1_set_to_der(values, values_len, out, outlen) != 1) { + error_print(); + return -1; + } return 1; } int x509_attribute_from_der( - int *oid, uint32_t *nodes, size_t *nodes_count, - const uint8_t **values, size_t *valueslen, + int *oid, uint32_t *nodes, size_t *nodes_cnt, + const uint8_t **values, size_t *values_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *p; + size_t len; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + *oid = OID_undef; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (asn1_object_identifier_from_der(oid, nodes, nodes_count, &data, &datalen) != 1 - || asn1_set_from_der(values, valueslen, &data, &datalen) != 1 - || datalen > 0) { + if (asn1_object_identifier_from_der(nodes, nodes_cnt, &p, &len) != 1 + || asn1_set_from_der(values, values_len, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { error_print(); return -1; } return 1; } - -/* - -9 - - BasicConstraints ::= SEQUENCE { - cA BOOLEAN DEFAULT FALSE, - pathLenConstraint INTEGER (0..MAX) OPTIONAL } - - FIXME: 从这个类型看起来,一个 SEQUENCE 中的数据可能是空的 - 但是问题是,如果这两个元素都没有内容,那么这个扩展就完全没有必要提供了! - - - 如果一个证书是CA证书,那么必须包含这个扩展 - - 没有为这个扩展建立一个独立的对象,这是因为在 x509_certificate_set_ 系列函数中 - 如果有一个独立的对象,那么会增加接口的复杂度。 - -一般来说在完成了证书的解析后,证书对象中有所有的扩展列表,有了扩展的OID,但是这些扩展的内容还没有解析 -现在还不太确定到底在什么时候需要获取某个证书扩展的内容,以及以何种方式获取 -可能还要等到验证证书链的时候才能定下来 - -*/ - - - - - -int x509_basic_constraints_to_der(int is_ca_cert, // 必须设置为 0 或 1,如果设为 0 那么不编码 - int cert_chain_maxlen, // -1 means omitted,FIXME: 应该设置一个最大值 - uint8_t **out, size_t *outlen) +int x509_attribute_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - size_t len = 0; - if (is_ca_cert) { - if (asn1_boolean_to_der(ASN1_TRUE, NULL, &len) != 1) { - error_print(); - return -1; - } + uint32_t nodes[32]; + size_t nodes_cnt; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + asn1_object_identifier_print(fp, fmt, ind, "type", NULL, nodes, nodes_cnt); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "values", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_attributes_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; } - if (cert_chain_maxlen >= 0) { - if (asn1_int_to_der((uint32_t)cert_chain_maxlen, NULL, &len) != 1) { - error_print(); - return -1; - } - } - asn1_sequence_header_to_der(len, out, outlen); - if (is_ca_cert) { - if (asn1_boolean_to_der(ASN1_TRUE, out, outlen) != 1) { - error_print(); - return -1; - } - } - if (cert_chain_maxlen >= 0) { - if (asn1_int_to_der((uint32_t)cert_chain_maxlen, out, outlen) != 1) { + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { error_print(); return -1; } + x509_attribute_print(fp, fmt, ind, "Attribute", p, len); } return 1; } -// 解码的时候如果 is_ca_cert 没有,那么会强制设置为0,因此从本函数无法知道 is_ca_cert 是否被编码 -// 如果 cert_chain_maxlen 没有编码,那么这个值会被强制设置为 -1 -int x509_basic_constraints_from_der(int *is_ca_cert, int *cert_chain_maxlen, const uint8_t **in, size_t *inlen) +int x509_basic_constraints_to_der(int ca, int path_len_cons, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (asn1_boolean_to_der(ca, NULL, &len) < 0 + || asn1_int_to_der(path_len_cons, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_boolean_to_der(ca, out, outlen) < 0 + || asn1_int_to_der(path_len_cons, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; - int maxlen; + const uint8_t *d; + size_t dlen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); return ret; } - if ((ret = asn1_boolean_from_der(is_ca_cert, &data, &datalen)) < 0) { - error_print(); - return -1; - } else if (ret == 0) { - *is_ca_cert = -1; - } + *ca = 0; + *path_len_cons = 0; // FIXME: 默认值应该设置为多少? - if ((ret = asn1_int_from_der(&maxlen, &data, &datalen)) < 0 - || datalen > 0) { + if (asn1_boolean_from_der(ca, &d, &dlen) < 0 + || asn1_int_from_der(path_len_cons, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; - } else if (ret == 0) { - *cert_chain_maxlen = -1; - } else { - if (maxlen > 6) { - error_print(); - return -1; - } - *cert_chain_maxlen = (int)maxlen; } return 1; } -int x509_basic_constraints_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) +int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - int is_ca_cert; - int cert_chain_maxlen; + int ret, val; - if (x509_basic_constraints_from_der(&is_ca_cert, &cert_chain_maxlen, &data, &datalen) != 1) { - error_print(); - return -1; - } - if (datalen) { - error_print(); - return -1; - } - if (is_ca_cert >= 0) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; - format_print(fp, format, indent, "cA : %s\n", is_ca_cert ? "true" : "false"); - - } - if (cert_chain_maxlen >= 0) { - format_print(fp, format, indent, "pathLenConstraint : %d\n", cert_chain_maxlen); - } + if ((ret = asn1_boolean_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "cA: %s\n", val ? "True" : "False"); + if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "pathLenConstraint: %d\n", val); + if (asn1_length_is_zero(dlen) != 1) goto err; return 1; +err: + error_print(); + return -1; } -/* -10 -GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree - -GeneralSubtree ::= SEQUENCE { - base GeneralName, - minimum [0] IMPLICIT INTEGER (0..MAX) DEFAULT 0, - maximum [1] IMPLICIT INTEGER (0..MAX) OPTIONAL } - - - 这里还是要用到GeneralName,这个类型非常难处理 - - 如果比较难构造,是否我们目前只支持解析,不支持构造呢? - - - 这个比较复杂的是其中的两个元素都是SEQUENCE OF SEQUENCE, - 这意味着我们必须对这种常见的形式给出一个统一的解析方案 - -*/ - - - int x509_general_subtree_to_der( - int base_choise, const uint8_t *base_data, size_t base_datalen, + int base_choice, const uint8_t *base, size_t base_len, int minimum, int maximum, uint8_t **out, size_t *outlen) { size_t len = 0; - - x509_general_name_to_der(base_choise, base_data, base_datalen, NULL, &len); - asn1_implicit_int_to_der(0, minimum, NULL, &len); - asn1_implicit_int_to_der(1, maximum, NULL, &len); - - asn1_sequence_header_to_der(len, out, outlen); - - x509_general_name_to_der(base_choise, base_data, base_datalen, out, outlen); - asn1_implicit_int_to_der(0, minimum, out, outlen); - asn1_implicit_int_to_der(1, maximum, out, outlen); - + if (x509_general_name_to_der(base_choice, base, base_len, NULL, &len) != 1 + || asn1_implicit_int_to_der(0, minimum, NULL, &len) < 0 + || asn1_implicit_int_to_der(1, maximum, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_general_name_to_der(base_choice, base, base_len, out, outlen) != 1 + || asn1_implicit_int_to_der(0, minimum, out, outlen) < 0 + || asn1_implicit_int_to_der(1, maximum, out, outlen) < 0) { + error_print(); + return -1; + } return 1; } int x509_general_subtree_from_der( - int *base_choice, const uint8_t **base_data, size_t *base_datalen, + int *base_choice, const uint8_t **base, size_t *base_len, int *minimum, int *maximum, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *d; + size_t dlen; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - if (x509_general_name_from_der(base_choice, base_data, base_datalen, &data, &datalen) != 1 - || asn1_implicit_int_from_der(0, minimum, &data, &datalen) < 0 - || asn1_implicit_int_from_der(1, maximum, &data, &datalen) < 0 - || datalen > 0) { + *minimum = 0; + *maximum = -1; + if (x509_general_name_from_der(base_choice, base, base_len, &d, &dlen) != 1 + || asn1_int_from_der(minimum, &d, &dlen) < 0 + || asn1_int_from_der(maximum, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { error_print(); - return ret; + return -1; + } + return 1; +} + +int x509_general_subtree_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, choice, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (x509_general_name_from_der(&choice, &p, &len, &d, &dlen) != 1) goto err; + x509_general_name_print(fp, fmt, ind, "base", choice, p, len); + if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "minimum: %d\n", val); + if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "maximum: %d\n", val); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_general_subtrees_add_general_subtree(uint8_t *d, size_t *dlen, size_t maxlen, + int base_choice, const uint8_t *base, size_t base_len, + int minimum, int maximum) +{ + error_print(); + return -1; +} + +int x509_general_subtrees_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_general_subtree_print(fp, fmt, ind, "GeneralSubtree", p, len); } - return 1; } -/* -NameConstraints ::= SEQUENCE { - permittedSubtrees [0] GeneralSubtrees OPTIONAL, - excludedSubtrees [1] GeneralSubtrees OPTIONAL } -*/ int x509_name_constraints_to_der( - const X509_GENERAL_SUBTREES *permitted_subtrees, - const X509_GENERAL_SUBTREES *excluded_subtrees, + const uint8_t *permitted_subtrees, size_t permitted_subtrees_len, + const uint8_t *excluded_subtrees, size_t excluded_subtrees_len, uint8_t **out, size_t *outlen) { size_t len = 0; - - x509_general_subtrees_to_der(permitted_subtrees, NULL, &len); - x509_general_subtrees_to_der(excluded_subtrees, NULL, &len); - - asn1_sequence_header_to_der(len, out, outlen); - x509_general_subtrees_to_der(permitted_subtrees, out, outlen); - x509_general_subtrees_to_der(excluded_subtrees, out, outlen); - + if (asn1_implicit_sequence_to_der(0, permitted_subtrees, permitted_subtrees_len, NULL, &len) < 0 + || asn1_implicit_sequence_to_der(1, excluded_subtrees, excluded_subtrees_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_implicit_sequence_to_der(0, permitted_subtrees, permitted_subtrees_len, out, outlen) < 0 + || asn1_implicit_sequence_to_der(1, excluded_subtrees, excluded_subtrees_len, out, outlen) < 0) { + error_print(); + return -1; + } return 1; } int x509_name_constraints_from_der( - X509_GENERAL_SUBTREES *permitted_subtrees, - X509_GENERAL_SUBTREES *excluded_subtrees, + const uint8_t **permitted_subtrees, size_t *permitted_subtrees_len, + const uint8_t **excluded_subtrees, size_t *excluded_subtrees_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *d; + size_t dlen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - - if (x509_general_subtrees_from_der(permitted_subtrees, &data, &datalen) < 0 - || x509_general_subtrees_from_der(excluded_subtrees, &data, &datalen) < 0 - || datalen > 0) { - error_print(); - return -1; - } - - return 1; -} - - -/* -11 -PolicyConstraints ::= SEQUENCE { - requireExplicitPolicy [0] IMPLICIT INTEGER (0..MAX) OPTIONAL, - inhibitPolicyMapping [1] IMPLICIT INTEGER (0..MAX) OPTIONAL -} - -Conforming CAs MUST mark this extension as critical. -*/ - -int x509_policy_constraints_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent) -{ - int require_explicit_policy = -1; - int inhibit_policy_mapping = -1; - if (x509_policy_constraints_from_der(&require_explicit_policy, &inhibit_policy_mapping, &p, &len) != 1) { - error_print(); - return -1; - } - format_print(fp, format, indent, "policyConstraints:\n"); - if (require_explicit_policy >= 0) { - format_print(fp, format, indent+4, "requireExplicitPolicy: %d\n", require_explicit_policy); - } - if (inhibit_policy_mapping >= 0) { - format_print(fp, format, indent+4, "inhibitPolicyMapping: %d\n", inhibit_policy_mapping); - } - if (len) { + *permitted_subtrees = NULL; + *permitted_subtrees_len = 0; + *excluded_subtrees = NULL; + *excluded_subtrees_len = 0; + if (asn1_implicit_sequence_from_der(0, permitted_subtrees, permitted_subtrees_len, &d, &dlen) < 0 + || asn1_implicit_sequence_from_der(1, excluded_subtrees, excluded_subtrees_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } return 1; } -int x509_policy_constraints_to_der(int require_explicit_policy, int inhibit_policy_mapping, uint8_t **out, size_t *outlen) -{ - size_t len = 0; - - asn1_implicit_int_to_der(0, require_explicit_policy, NULL, &len); - asn1_implicit_int_to_der(1, inhibit_policy_mapping, NULL, &len); - - asn1_sequence_header_to_der(len, out, outlen); - - asn1_implicit_int_to_der(0, require_explicit_policy, out, outlen); - asn1_implicit_int_to_der(1, inhibit_policy_mapping, out, outlen); - - return 1; -} - -int x509_policy_constraints_from_der(int *require_explicit_policy, int *inhibit_policy_mapping, const uint8_t **in, size_t *inlen) +int x509_name_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - - if (asn1_implicit_int_from_der(0, require_explicit_policy, &data, &datalen) < 0 - || asn1_implicit_int_from_der(1, inhibit_policy_mapping, &data, &datalen) < 0 - || datalen > 0) { - error_print(); - return -1; - } + const uint8_t *p; + size_t len; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + if ((ret = asn1_implicit_sequence_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_subtrees_print(fp, fmt, ind, "permittedSubtrees", p, len); + if ((ret = asn1_implicit_sequence_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_subtrees_print(fp, fmt, ind, "excludedSubtrees", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; return 1; +err: + error_print(); + return -1; } - - - -/* -12 -ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF OBJECT IDENTIFIER - - ExtKeyUsage OIDs: - - OID_kp_serverAuth, - OID_kp_clientAuth, - OID_kp_codeSigning, - OID_kp_emailProtection, - OID_kp_timeStamping, - OID_kp_OCSPSigning, - - -这里的问题是,有可能出现新的OID,比如微软定义的或者Google定义的 -所以在解码的时候不能假定所有的OID都是已知的 - -但是在设置的时候应该只能设置已知的OID - -解析的时候不可能只用oid来承接了,必须用带buffer的来承接 -*/ - -int x509_ext_key_usage_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent) -{ - const uint8_t *data; - size_t datalen; - - if (asn1_sequence_from_der(&data, &datalen, &p, &len) != 1) { - error_print(); - return -1; - } - format_print(fp, format, indent, "extKeyUsages:\n"); - while (datalen) { - int key_usage; - uint32_t nodes[32]; - size_t nodes_count; - size_t i; - - if (asn1_object_identifier_from_der(&key_usage, nodes, &nodes_count, &data, &datalen) != 1) { - error_print(); - return -1; - } - format_print(fp, format, indent + 4, "%s (", "unknown"); - for (i = 0; i < nodes_count - 1; i++) { - fprintf(fp, "%d.", nodes[i]); - } - fprintf(fp, "%d)\n", nodes[i]); - } - - if (len) { - error_print(); - return -1; - } - return 1; -} - - -/* -## 13 CRLDistributionPoints - -SHOULD be non-critical - - - -实际上我现在没有一个统一的方法去处理CHOICE类型的设置和解析 -首先是否要给一个CHOICE类型设置一个新的对象,按照我们的设置,如果设置的话,就需要这个对象能够承载内部数据 - - - - CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint - - ReasonFlags ::= BIT STRING { - unused (0), - keyCompromise (1), - cACompromise (2), - affiliationChanged (3), - superseded (4), - cessationOfOperation (5), - certificateHold (6), - privilegeWithdrawn (7), - aACompromise (8) } - -*/ - - -/* -DistributionPointName ::= CHOICE { - fullName [0] IMPLICIT GeneralNames, - nameRelativeToCRLIssuer [1] IMPLICIT RelativeDistinguishedName } - - GeneralNames 类型为 SEQUENCE OF - RelativeDistinguishedName 类型为 SET OF - 因此需要为 DistributionPointName 建立一个新类型 - - 这两个类型实际上都是 SEQUENCE OF/SET OF - - 因为GeneralNames是一个类型,因此污染了X509_CRL_DISTRIBUTION_POINT_NAME - - -*/ - -int x509_distribution_point_name_to_der(const X509_DISTRIBUTION_POINT_NAME *a, uint8_t **out, size_t *outlen) -{ - - return 1; -} - -int x509_distribution_point_name_from_der(X509_DISTRIBUTION_POINT_NAME *a, const uint8_t **in, size_t *inlen) -{ - return 1; -} - -int x509_distribution_point_to_der( // DistributionPoint - const X509_DISTRIBUTION_POINT_NAME *dist_point_name, // [0] EXPLICIT OPTIONAL - int reason_bits, // [1] IMPLICIT OPTIONAL - const X509_GENERAL_NAMES *crl_issuer, // [2] IMPLICIT OPTIONAL +int x509_policy_constraints_to_der( + int require_explicit_policy, + int inhibit_policy_mapping, uint8_t **out, size_t *outlen) { size_t len = 0; - size_t sublen = 0; + if (asn1_implicit_int_to_der(0, require_explicit_policy, NULL, &len) < 0 + || asn1_implicit_int_to_der(1, inhibit_policy_mapping, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_implicit_int_to_der(0, require_explicit_policy, out, outlen) < 0 + || asn1_implicit_int_to_der(1, inhibit_policy_mapping, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} - //x509_distribution_point_name_to_der(dist_point_name, NULL, &sublen); - asn1_explicit_to_der(0, NULL, sublen, NULL, &len); - asn1_implicit_bits_to_der(1, reason_bits, NULL, &len); - x509_implicit_general_names_to_der(2, crl_issuer, NULL, &len); +int x509_policy_constraints_from_der( + int *require_explicit_policy, + int *inhibit_policy_mapping, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; - asn1_sequence_header_to_der(len, out, outlen); - asn1_explicit_header_to_der(0, sublen, out, outlen); - x509_distribution_point_name_to_der(dist_point_name, out, outlen); - asn1_implicit_bits_to_der(1, reason_bits, out, outlen); - x509_implicit_general_names_to_der(2, crl_issuer, out, outlen); + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + *require_explicit_policy = -1; + *inhibit_policy_mapping = -1; + if (asn1_implicit_int_from_der(0, require_explicit_policy, &d, &dlen) < 0 + || asn1_implicit_int_from_der(1, inhibit_policy_mapping, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} +int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "requireExplicitPolicy: %d\n", val); + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "inhibitPolicyMapping: %d\n", val); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_ext_key_usage_to_der(const int *oids, size_t oids_cnt, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + size_t i; + + if (oids_cnt > X509_MAX_KEY_PURPOSES) { + error_print(); + return -1; + } + for (i = 0; i < oids_cnt; i++) { + if (x509_key_purpose_to_der(oids[i], NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_sequence_header_to_der(len, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < oids_cnt; i++) { + if (x509_key_purpose_to_der(oids[i], out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + *oids_cnt = 0; + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + while (len && (*oids_cnt < max_cnt)) { + if (x509_key_purpose_from_der(oids, &p, &len) != 1) { + error_print(); + return -1; + } + oids++; + (*oids_cnt)++; + } + if (len) { + error_print(); + return -1; + } + return 1; +} + +int x509_ext_key_usage_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int oid; + format_print(fp, fmt, ind, "%s: ", label); + while (dlen) { + if (x509_key_purpose_from_der(&oid, &d, &dlen) != 1) { + error_print(); + return -1; + } + fprintf(fp, "%s%s", x509_key_purpose_name(oid), dlen ? ", " : ""); + } + fprintf(fp, "\n"); + return 1; +} + +static const char *x509_revoke_reasons[] = { + "unused", + "keyCompromise", + "cACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "privilegeWithdrawn", + "aACompromise", +}; + +static size_t x509_revoke_reasons_count = + sizeof(x509_revoke_reasons)/sizeof(x509_revoke_reasons[0]); + +int x509_revoke_reasons_print(FILE *fp, int fmt, int ind, const char *label, int bits) +{ + return asn1_bits_print(fp, fmt, ind, label, x509_revoke_reasons, x509_revoke_reasons_count, bits); +} + +int x509_distribution_point_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + switch (choice) { + case 0: + case 1: + if (asn1_implicit_to_der(choice, d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; + default: + error_print(); + return -1; + } +} + +int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_implicit_from_der(*choice, d, dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return -1; + } + switch (*choice) { + case 0: + case 1: + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label, int choice, const uint8_t *d, size_t dlen) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + switch (choice) { + case 0: return x509_general_names_print(fp, fmt, ind, "fullName", d, dlen); + case 1: return x509_rdn_print(fp, fmt, ind, "nameRelativeToCRLIssuer", d, dlen); + default: + error_print(); + return -1; + } +} + +int x509_distribution_point_to_der( + int dist_point_choice, const uint8_t *dist_point_d, size_t dist_point_dlen, + int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + const uint8_t *dist_point; + size_t dist_point_len = 0; + + x509_distribution_point_name_to_der(dist_point_choice, dist_point_d, dist_point_dlen, NULL, &dist_point_len); + + if (asn1_explicit_to_der(0, dist_point, dist_point_len, NULL, &len) < 0 + || asn1_implicit_bits_to_der(1, reasons, NULL, &len) < 0 + || asn1_implicit_sequence_to_der(2, crl_issuer, crl_issuer_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_explicit_to_der(0, dist_point, dist_point_len, out, outlen) < 0 + || asn1_implicit_bits_to_der(1, reasons, out, outlen) < 0 + || asn1_implicit_sequence_to_der(2, crl_issuer, crl_issuer_len, out, outlen) < 0) { + error_print(); + return -1; + } return 1; } int x509_distribution_point_from_der( - X509_DISTRIBUTION_POINT_NAME *dist_point_name, - int *reason_bits, - X509_GENERAL_NAMES *crl_issuer, + int *dist_point_choice, const uint8_t **dist_point_d, size_t *dist_point_dlen, + int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len, const uint8_t **in, size_t *inlen) { int ret; - const uint8_t *data; - size_t datalen; - const uint8_t *subdata; - size_t subdatalen; + const uint8_t *p; + size_t len; + const uint8_t *dist_point; + size_t dist_point_len; - if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) { + if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } - - if (asn1_explicit_from_der(0, &subdata, &subdatalen, &data, &datalen) < 0 - || x509_distribution_point_name_from_der(dist_point_name, &subdata, &subdatalen) != 1 - || subdatalen > 0 - //|| asn1_implicit_bit_string_from_der(1, reason_bits, &data, &datalen) < 0 - || x509_implicit_general_names_from_der(2, crl_issuer, &data, &datalen) < 0 - || datalen > 0) { + if (asn1_explicit_from_der(0, &dist_point, &dist_point_len, &p, &len) < 0 + || asn1_implicit_bits_from_der(1, reasons, &p, &len) < 0 + || asn1_implicit_sequence_from_der(2, crl_issuer, crl_issuer_len, &p, &len) < 0 + || asn1_length_is_zero(len) != 1) { error_print(); return -1; } - - return 1; -} - -/* - - CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint - -*/ - - - - - -/* -14 -InhibitAnyPolicy ::= INTEGER (0..MAX) - -Conforming CAs MUST mark this extension as critical. -*/ - - - -/* -15 -FreshestCRL ::= CRLDistributionPoints -MUST be marked as non-critical by conforming CAs. -*/ - - - - - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Public APIs -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -struct { - int oid; - int is_critical; - int tag; -} x509_exts[] = { - { OID_ce_authorityKeyIdentifier, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_subjectKeyIdentifier, 1, ASN1_TAG_OCTET_STRING }, - { OID_ce_keyUsage, 1, ASN1_TAG_BIT_STRING }, - { OID_ce_certificatePolicies, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_policyMappings, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_subjectAltName, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_issuerAltName, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_subjectDirectoryAttributes, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_basicConstraints, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_nameConstraints, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_policyConstraints, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_extKeyUsage, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_crlDistributionPoints, 1, ASN1_TAG_SEQUENCE }, - { OID_ce_inhibitAnyPolicy, 1, ASN1_TAG_INTEGER }, - { OID_ce_freshestCRL, 1, ASN1_TAG_SEQUENCE }, -}; - - - - -int x509_certificate_set_authority_key_identifier(X509_CERTIFICATE *cert, - int is_critical, - const uint8_t *keyid, size_t keyid_len, - const X509_GENERAL_NAMES *issuer, - const uint8_t *serial_number, size_t serial_number_len) -{ - int oid = OID_ce_authorityKeyIdentifier; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_authority_key_identifier_to_der(keyid, keyid_len, issuer, serial_number, serial_number_len, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { + if (x509_distribution_point_name_from_der(dist_point_choice, dist_point_d, dist_point_dlen, &dist_point, &dist_point_len) != 1 + || asn1_length_is_zero(dist_point_len) != 1) { error_print(); return -1; } return 1; } -int x509_certificate_set_subject_key_identifier(X509_CERTIFICATE *cert, - int is_critical, - const uint8_t *keyid, size_t keyid_len) +int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - int oid = OID_ce_subjectKeyIdentifier; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (asn1_octet_string_to_der(keyid, keyid_len, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_generate_subject_key_identifier(X509_CERTIFICATE *cert, int is_critical) -{ - uint8_t keyid[32]; - sm2_public_key_digest(&cert->tbs_certificate.subject_public_key_info.sm2_key, keyid); - x509_certificate_set_subject_key_identifier(cert, is_critical, keyid, sizeof(keyid)); - return 1; -} - -int x509_subject_key_identifier_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) -{ - const uint8_t *keyid; - size_t keyidlen; - if (asn1_octet_string_from_der(&keyid, &keyidlen, &data, &datalen) != 1 - || datalen) { - error_print(); - return -1; - } - format_bytes(fp, format, indent, "keyIdentifier: ", keyid, keyidlen); - return 1; -} - -int x509_certificate_set_key_usage(X509_CERTIFICATE *cert, - int is_critical, - int usages) -{ - int oid = OID_ce_keyUsage; - uint8_t data[32]; - uint8_t *p = data; - size_t datalen = 0; - -/* - if (//asn1_bits_to_der(usages, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } -*/ - return 1; -} - -int x509_certificate_set_certificate_policies(X509_CERTIFICATE *cert, - int is_critical, - const X509_CERTIFICATE_POLICIES *policies) -{ - int oid = OID_ce_certificatePolicies; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_certificate_policies_to_der(policies, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_policy_mappings(X509_CERTIFICATE *cert, - int is_critical, - const X509_POLICY_MAPPINGS *mappings) -{ - int oid = OID_ce_policyMappings; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_policy_mappings_to_der(mappings, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_subject_alt_name(X509_CERTIFICATE *cert, - int is_critical, - const X509_GENERAL_NAMES *name) -{ - int oid = OID_ce_subjectAltName; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_general_names_to_der(name, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_issuer_alt_name(X509_CERTIFICATE *cert, - int is_critical, - const X509_GENERAL_NAMES *name) -{ - int oid = OID_ce_issuerAltName; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_general_names_to_der(name, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_subject_directory_attributes(X509_CERTIFICATE *cert, - int is_critical, - const X509_ATTRIBUTES *attrs) -{ - int oid = OID_ce_subjectDirectoryAttributes; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_attributes_to_der(attrs, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_basic_constraints(X509_CERTIFICATE *cert, - int is_critical, - int is_ca_cert, - int cert_chain_maxlen) -{ - int oid = OID_ce_basicConstraints; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_basic_constraints_to_der(is_ca_cert, cert_chain_maxlen, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_name_constraints(X509_CERTIFICATE *cert, - int is_critical, - const X509_GENERAL_SUBTREES *permitted_subtrees, - const X509_GENERAL_SUBTREES *excluded_subtrees) -{ - int oid = OID_ce_nameConstraints; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_name_constraints_to_der(permitted_subtrees, excluded_subtrees, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_policy_constraints(X509_CERTIFICATE *cert, - int is_critical, - int require_explicit_policy, - int inhibit_policy_mapping) -{ - int oid = OID_ce_policyConstraints; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_policy_constraints_to_der(require_explicit_policy, inhibit_policy_mapping, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_ext_key_usage(X509_CERTIFICATE *cert, - int is_critical, - const int *key_purpose_oids, size_t key_purpose_oids_count) -{ - int oid = OID_ce_extKeyUsage; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_ext_key_usage_to_der(key_purpose_oids, key_purpose_oids_count, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_crl_distribution_points(X509_CERTIFICATE *cert, - int is_critical, - const X509_CRL_DISTRIBUTION_POINTS *crl_dist_points) -{ - int oid = OID_ce_crlDistributionPoints; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_crl_distribution_points_to_der(crl_dist_points, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_inhibit_any_policy(X509_CERTIFICATE *cert, - int is_critical, - int skip_certs) -{ - int oid = OID_ce_inhibitAnyPolicy; - uint8_t data[16]; - uint8_t *p = data; - size_t datalen = 0; - - if (asn1_int_to_der(skip_certs, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_freshest_crl(X509_CERTIFICATE *cert, - int is_critical, - const X509_CRL_DISTRIBUTION_POINTS *crl_dist_points) -{ - int oid = OID_ce_freshestCRL; - uint8_t data[1024]; - uint8_t *p = data; - size_t datalen = 0; - - if (x509_crl_distribution_points_to_der(crl_dist_points, &p, &datalen) != 1 - || x509_certificate_add_extension(cert, oid, is_critical, data, datalen) != 1) { - error_print(); - return -1; - } - return 1; -} - -// x509_certificate_get_[extension_name] -// return values: -// ret == 0 no such extension -// ret < 0 error -// ret == 1 ok - - -int x509_certificate_get_authority_key_identifier(const X509_CERTIFICATE *cert, - int *is_critical, - const uint8_t **keyid, size_t *keyid_len, - X509_GENERAL_NAMES *issuer, - const uint8_t **serial_number, size_t *serial_number_len) -{ - int oid = OID_ce_authorityKeyIdentifier; int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *p; + size_t len; + int bits; - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_authority_key_identifier_from_der(keyid, keyid_len, issuer, serial_number, serial_number_len, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if ((ret = asn1_explicit_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) { + int choice; + const uint8_t *name; + size_t namelen; + + if (x509_distribution_point_name_from_der(&choice, &name, &namelen, &p, &len) != 1) goto err; + x509_distribution_point_name_print(fp, fmt, ind, "DistributionPointName", choice, name, namelen); + if (asn1_length_is_zero(len) != 1) goto err; } + if ((ret = asn1_implicit_bits_from_der(1, &bits, &d, &dlen)) < 0) goto err; + if (ret) x509_revoke_reasons_print(fp, fmt, ind, "reasons", bits); + if ((ret = asn1_implicit_sequence_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_general_names_print(fp, fmt, ind, "cRLIssuer", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; return 1; +err: + error_print(); + return -1; } -int x509_certificate_get_subject_key_identifier(const X509_CERTIFICATE *cert, - int *is_critical, - const uint8_t **keyid, size_t *keyid_len) +int x509_distribution_points_add_distribution_point(uint8_t *d, size_t *dlen, size_t maxlen, + int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len, + int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len) { - int oid = OID_ce_subjectKeyIdentifier; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_octet_string_from_der(keyid, keyid_len, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - if (*keyid_len <= 0) { - error_print(); - return -1; - } - return 1; + error_print(); + return -1; } -int x509_certificate_get_key_usage(const X509_CERTIFICATE *cert, - int *is_critical, - int *usage_bits) +int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - int oid = OID_ce_keyUsage; - int ret; - const uint8_t *data; - size_t datalen; + const uint8_t *p; + size_t len; - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; } - if (asn1_bits_from_der(usage_bits, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - // 应该检查一下bits对不对 - return 1; -} - - -#if 0 - 983 /* - 984 3 - 985 KeyUsage ::= BIT STRING { - 986 digitalSignature (0), - 987 nonRepudiation (1), -- recent editions of X.509 have - 988 -- renamed this bit to contentCommitment - 989 keyEncipherment (2), - 990 dataEncipherment (3), - 991 keyAgreement (4), - 992 keyCertSign (5), - 993 cRLSign (6), - 994 encipherOnly (7), - 995 decipherOnly (8) } - 996 */ - -#endif - - -int x509_key_usage_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) -{ - int usage; - if (asn1_bits_from_der(&usage, &data, &datalen) != 1) { - error_print(); - return -1; - } - format_print(fp, format, indent, "%s", usage == 0 ? "(null)" : ""); - if (usage & (1 << X509_ku_digital_signature)) fprintf(fp, "DigitalSignature, "); - if (usage & (1 << X509_ku_non_repudiation)) fprintf(fp, "NonRepudiation, "); - if (usage & (1 << X509_ku_key_encipherment)) fprintf(fp, "KeyEncipherment, "); - if (usage & (1 << X509_ku_data_encipherment)) fprintf(fp, "DataEncipherment, "); - if (usage & (1 << X509_ku_key_agreement)) fprintf(fp, "KeyAgreement, "); - if (usage & (1 << X509_ku_key_cert_sign)) fprintf(fp, "KeyCertSign, "); - if (usage & (1 << X509_ku_crl_sign)) fprintf(fp, "CRLSign, "); - if (usage & (1 << X509_ku_encipher_only)) fprintf(fp, "EncipherOnly, "); - if (usage & (1 << X509_ku_decipher_only)) fprintf(fp, "DecipherOnly, "); - // FIXME: more bits ? - fprintf(fp, "\n"); - - if (datalen) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_certificate_policies(const X509_CERTIFICATE *cert, - int *is_critical, - X509_CERTIFICATE_POLICIES *policies) -{ - int oid = OID_ce_certificatePolicies; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_certificate_policies_from_der(policies, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_policy_mappings(const X509_CERTIFICATE *cert, - int *is_critical, - X509_POLICY_MAPPINGS *mappings) -{ - int oid = OID_ce_policyMappings; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_policy_mappings_from_der(mappings, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_subject_directory_attributes(const X509_CERTIFICATE *cert, - int *is_critical, - X509_ATTRIBUTES *attrs) -{ - int oid = OID_ce_subjectDirectoryAttributes; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_attributes_from_der(attrs, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_basic_constraints(const X509_CERTIFICATE *cert, - int *is_critical, - int *is_ca_cert, - int *cert_chain_maxlen) -{ - int oid = OID_ce_basicConstraints; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_basic_constraints_from_der(is_ca_cert, cert_chain_maxlen, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_name_constraints(X509_CERTIFICATE *cert, - int *is_critical, - X509_GENERAL_SUBTREES *permitted_subtrees, - X509_GENERAL_SUBTREES *excluded_subtrees) -{ - int oid = OID_ce_nameConstraints; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_name_constraints_from_der(permitted_subtrees, excluded_subtrees, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_policy_constraints(const X509_CERTIFICATE *cert, - int *is_critical, - int *requireExplicitPolicy, - int *inhibitPolicyMapping) -{ - int oid = OID_ce_policyConstraints; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_policy_constraints_from_der(requireExplicitPolicy, inhibitPolicyMapping, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - } - return 1; -} - -int x509_certificate_get_ext_key_usage(const X509_CERTIFICATE *cert, - int *is_critical, - int *key_purposes, size_t *key_purposes_count) -{ - int oid = OID_ce_extKeyUsage; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_ext_key_usage_from_der(key_purposes, key_purposes_count, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_crl_distribution_points(const X509_CERTIFICATE *cert, - int *is_critical, - X509_CRL_DISTRIBUTION_POINTS *crl_dist_points) -{ - int oid = OID_ce_crlDistributionPoints; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_crl_distribution_points_from_der(crl_dist_points, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_inhibit_any_policy(const X509_CERTIFICATE *cert, - int *is_critical, - int *skip_certs) -{ - int oid = OID_ce_inhibitAnyPolicy; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_int_from_der(skip_certs, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_get_freshest_crl(const X509_CERTIFICATE *cert, - int *is_critical, - X509_CRL_DISTRIBUTION_POINTS *crl_dist_points) -{ - int oid = OID_ce_freshestCRL; - int ret; - const uint8_t *data; - size_t datalen; - - if ((ret = x509_certificate_get_extension_from_oid(cert, oid, is_critical, &data, &datalen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_crl_distribution_points_from_der(crl_dist_points, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - return -1; + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_distribution_point_print(fp, fmt, ind, "DistributionPoint", p, len); } return 1; } diff --git a/src/x509_lib.c b/src/x509_lib.c deleted file mode 100644 index c4f31883..00000000 --- a/src/x509_lib.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the GmSSL Project. - * (http://gmssl.org/)" - * - * 4. The name "GmSSL Project" must not be used to endorse or promote - * products derived from this software without prior written - * permission. For written permission, please contact - * guanzhi1980@gmail.com. - * - * 5. Products derived from this software may not be called "GmSSL" - * nor may "GmSSL" appear in their names without prior written - * permission of the GmSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the GmSSL Project - * (http://gmssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* -应用应该只调用这个文件中实现的接口 - -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -int x509_certificate_set_version(X509_CERTIFICATE *cert, int version) -{ - if (version < X509_version_v1 || version > X509_version_v3) { - error_print(); - return -1; - } - cert->tbs_certificate.version = version; - return 1; -} - -int x509_certificate_set_serial_number(X509_CERTIFICATE *cert, const uint8_t *sn, size_t snlen) -{ - if (!cert || !sn || snlen <= 0 || snlen > 20) { - error_print(); - return -1; - } - memcpy(cert->tbs_certificate.serial_number, sn, snlen); - cert->tbs_certificate.serial_number_len = snlen; - return 1; -} - -int x509_certificate_set_signature_algor_sm2(X509_CERTIFICATE *cert) -{ - cert->tbs_certificate.signature_algor = OID_sm2sign_with_sm3; - cert->signature_algor = OID_sm2sign_with_sm3; - return 1; -} - -int x509_certificate_set_issuer(X509_CERTIFICATE *cert, const X509_NAME *name) -{ - memcpy(&cert->tbs_certificate.issuer, name, sizeof(X509_NAME)); - return 1; -} - -int x509_certificate_set_subject(X509_CERTIFICATE *cert, const X509_NAME *name) -{ - memcpy(&cert->tbs_certificate.subject, name, sizeof(X509_NAME)); - return 1; -} - -int x509_certificate_set_validity(X509_CERTIFICATE *cert, time_t not_before, int days) -{ - if (x509_validity_set_days(&cert->tbs_certificate.validity, not_before, days) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_set_signature_algor(X509_CERTIFICATE *cert, int oid) -{ - cert->tbs_certificate.signature_algor = oid; - return 1; -} - -int x509_certificate_set_subject_public_key_info_sm2(X509_CERTIFICATE *cert, const SM2_KEY *sm2_key) -{ - X509_PUBLIC_KEY_INFO *pkey_info = &cert->tbs_certificate.subject_public_key_info; - x509_public_key_info_set_sm2(pkey_info, sm2_key); - return 1; -} - -int x509_certificate_set_issuer_unique_id(X509_CERTIFICATE *cert, const uint8_t *id, size_t idlen) -{ - memcpy(cert->tbs_certificate.issuer_unique_id, id, idlen); - cert->tbs_certificate.issuer_unique_id_len = idlen; - return 1; -} - -int x509_certificate_set_subject_unique_id(X509_CERTIFICATE *cert, const uint8_t *id, size_t idlen) -{ - memcpy(cert->tbs_certificate.subject_unique_id, id, idlen); - cert->tbs_certificate.subject_unique_id_len = idlen; - return 1; -} - -int x509_certificate_set_issuer_unique_id_from_public_key_sm2(X509_CERTIFICATE *cert, const SM2_KEY *sm2_key) -{ - uint8_t uniq_id[32]; - sm2_public_key_digest(sm2_key, uniq_id); - x509_certificate_set_issuer_unique_id(cert, uniq_id, sizeof(uniq_id)); - return 1; -} - -int x509_certificate_set_subject_unique_id_from_public_key_sm2(X509_CERTIFICATE *cert, const SM2_KEY *sm2_key) -{ - uint8_t uniq_id[32]; - sm2_public_key_digest(sm2_key, uniq_id); - x509_certificate_set_subject_unique_id(cert, uniq_id, sizeof(uniq_id)); - return 1; -} - - -int x509_certificate_sign_sm2(X509_CERTIFICATE *cert, const SM2_KEY *key) -{ - SM2_SIGN_CTX ctx; - uint8_t buf[1024]; - uint8_t *p = buf; - size_t len = 0; - - cert->signature_algor = OID_sm2sign_with_sm3; - x509_tbs_certificate_to_der(&cert->tbs_certificate, &p, &len); - if (sm2_sign_init(&ctx, key, SM2_DEFAULT_ID) != 1 - || sm2_sign_update(&ctx, buf, len) != 1 - || sm2_sign_finish(&ctx, cert->signature, &cert->signature_len) != 1) { - error_print(); - return -1; - } - - memset(&ctx, 0, sizeof(ctx)); - return 1; -} - -// 这个公钥应该是根据issuer name从签名的CA证书中取得的 -int x509_certificate_verify_sm2(const X509_CERTIFICATE *cert, const SM2_KEY *sm2_key) -{ - SM2_SIGN_CTX ctx; - uint8_t buf[1024]; - uint8_t *p = buf; - size_t len = 0; - - x509_tbs_certificate_to_der(&cert->tbs_certificate, &p, &len); - if (sm2_verify_init(&ctx, sm2_key, SM2_DEFAULT_ID) != 1 - || sm2_verify_update(&ctx, buf, len) != 1 - || sm2_verify_finish(&ctx, cert->signature, cert->signature_len) != 1) { - return -1; - } - - memset(&ctx, 0, sizeof(ctx)); - return 1; -} - -int x509_certificate_get_public_key_sm2(const X509_CERTIFICATE *cert, SM2_KEY *sm2_key) -{ - *sm2_key = cert->tbs_certificate.subject_public_key_info.sm2_key; - return 1; -} - - -int x509_certificate_verify_by_certificate(const X509_CERTIFICATE *cert, const X509_CERTIFICATE *cacert) -{ - int ret; - SM2_KEY ca_pubkey; - - if (x509_name_equ(&cert->tbs_certificate.issuer, &cacert->tbs_certificate.subject) != 1) { - error_print(); - return -1; - } - if (x509_certificate_get_public_key(cacert, &ca_pubkey) != 1) { - error_print(); - return -1; - } - if ((ret = x509_certificate_verify(cert, &ca_pubkey)) < 0) { - error_print(); - return -1; - } - return ret; -} - -int x509_certificate_from_pem_by_name(X509_CERTIFICATE *cert, FILE *fp, const X509_NAME *issuer) -{ - int ret; - for (;;) { - if ((ret = x509_certificate_from_pem(cert, fp)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_name_equ(&cert->tbs_certificate.subject, issuer) == 1) { - return 1; - } - } - return 0; -} diff --git a/src/x509_oid.c b/src/x509_oid.c new file mode 100644 index 00000000..5d8a3fb8 --- /dev/null +++ b/src/x509_oid.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static uint32_t oid_at_name[] = { oid_at,41 }; +static uint32_t oid_at_surname[] = { oid_at,4 }; +static uint32_t oid_at_given_name[] = { oid_at,42 }; +static uint32_t oid_at_initials[] = { oid_at,43 }; +static uint32_t oid_at_generation_qualifier[] = { oid_at,44 }; +static uint32_t oid_at_common_name[] = { oid_at,3 }; +static uint32_t oid_at_locality_name[] = { oid_at,7 }; +static uint32_t oid_at_state_or_province_name[] = { oid_at,8 }; +static uint32_t oid_at_organization_name[] = { oid_at,10 }; +static uint32_t oid_at_organizational_unit_name[] = { oid_at,11 }; +static uint32_t oid_at_title[] = { oid_at,12 }; +static uint32_t oid_at_dn_qualifier[] = { oid_at,46 }; +static uint32_t oid_at_country_name[] = { oid_at,6 }; +static uint32_t oid_at_serial_number[] = { oid_at,5 }; +static uint32_t oid_at_pseudonym[] = { oid_at,65 }; +static uint32_t oid_domain_component[] = { 0,9,2342,19200300,100,1,25 }; + +static const ASN1_OID_INFO x509_name_types[] = { + { OID_at_name, "name", oid_at_name, 3 }, + { OID_at_surname, "surname", oid_at_surname, 3 }, + { OID_at_given_name, "givenName", oid_at_given_name, 3 }, + { OID_at_initials, "initials", oid_at_initials, 3 }, + { OID_at_generation_qualifier, "generationQualifier", oid_at_generation_qualifier, 3 }, + { OID_at_common_name, "commonName", oid_at_common_name, 3 }, + { OID_at_locality_name, "localityName", oid_at_locality_name, 3 }, + { OID_at_state_or_province_name, "stateOrProvinceName", oid_at_state_or_province_name, 3 }, + { OID_at_organization_name, "organizationName", oid_at_organization_name, 3 }, + { OID_at_organizational_unit_name, "organizationalUnitName", oid_at_organizational_unit_name, 3 }, + { OID_at_title, "title", oid_at_title, 3 }, + { OID_at_dn_qualifier, "dnQualifier", oid_at_dn_qualifier, 3 }, + { OID_at_country_name, "countryName", oid_at_country_name, 3 }, + { OID_at_serial_number, "serialNumber", oid_at_serial_number, 3 }, + { OID_at_pseudonym, "pseudonym", oid_at_pseudonym, 3 }, + { OID_domain_component, "domainComponent", oid_domain_component, 7 }, +}; + +static const int x509_name_types_count + = sizeof(x509_name_types)/sizeof(x509_name_types[0]); + +const char *x509_name_type_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_name_types, x509_name_types_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_name_type_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_name_types, x509_name_types_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_name_type_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_name_types, x509_name_types_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_name_type_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const ASN1_OID_INFO *info; + + *oid = 0; + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if ((ret = asn1_oid_info_from_der(&info, x509_name_types, x509_name_types_count, &d, &dlen)) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return ret; + } + *oid = info->oid; + return 1; +} + + +static uint32_t oid_ce_subject_directory_attributes[] = { oid_ce,9 }; +static uint32_t oid_ce_subject_key_identifier[] = { oid_ce,14 }; +static uint32_t oid_ce_key_usage[] = { oid_ce,15 }; +static uint32_t oid_ce_subject_alt_name[] = { oid_ce,17 }; +static uint32_t oid_ce_issuer_alt_name[] = { oid_ce,18 }; +static uint32_t oid_ce_basic_constraints[] = { oid_ce,19 }; +static uint32_t oid_ce_name_constraints[] = { oid_ce,30 }; +static uint32_t oid_ce_crl_distribution_points[] = { oid_ce,31 }; +static uint32_t oid_ce_certificate_policies[] = { oid_ce,32 }; +static uint32_t oid_ce_policy_mappings[] = { oid_ce,33 }; +static uint32_t oid_ce_authority_key_identifier[] = { oid_ce,35 }; +static uint32_t oid_ce_policy_constraints[] = { oid_ce,36 }; +static uint32_t oid_ce_ext_key_usage[] = { oid_ce,37 }; +static uint32_t oid_ce_freshest_crl[] = { oid_ce,46 }; +static uint32_t oid_ce_inhibit_any_policy[] = { oid_ce,54 }; + +static const ASN1_OID_INFO x509_ext_ids[] = { + { OID_ce_authority_key_identifier, "AuthorityKeyIdentifier", oid_ce_authority_key_identifier, 4 }, + { OID_ce_subject_key_identifier, "SubjectKeyIdentifier", oid_ce_subject_key_identifier, 4 }, + { OID_ce_key_usage, "KeyUsage", oid_ce_key_usage, 4 }, + { OID_ce_certificate_policies, "CertificatePolicies", oid_ce_certificate_policies, 4 }, + { OID_ce_policy_mappings, "PolicyMappings", oid_ce_policy_mappings, 4 }, + { OID_ce_subject_alt_name, "SubjectAltName", oid_ce_subject_alt_name, 4 }, + { OID_ce_issuer_alt_name, "IssuerAltName", oid_ce_issuer_alt_name, 4 }, + { OID_ce_subject_directory_attributes, "SubjectDirectoryAttributes", oid_ce_subject_directory_attributes, 4 }, + { OID_ce_basic_constraints, "BasicConstraints", oid_ce_basic_constraints, 4 }, + { OID_ce_name_constraints, "NameConstraints", oid_ce_name_constraints, 4 }, + { OID_ce_policy_constraints, "PolicyConstraints", oid_ce_policy_constraints, 4 }, + { OID_ce_ext_key_usage, "ExtKeyUsage", oid_ce_ext_key_usage, 4 }, + { OID_ce_crl_distribution_points, "CRLDistributionPoints", oid_ce_crl_distribution_points, 4 }, + { OID_ce_inhibit_any_policy, "InhibitAnyPolicy", oid_ce_inhibit_any_policy, 4 }, + { OID_ce_freshest_crl, "FreshestCRL", oid_ce_freshest_crl, 4 }, +}; + +static const int x509_ext_ids_count = + sizeof(x509_ext_ids)/sizeof(x509_ext_ids[0]); + +const char *x509_ext_id_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_ext_ids, x509_ext_ids_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_ext_id_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_ext_ids, x509_ext_ids_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +int x509_ext_id_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + size_t len = 0; + if (!(info = asn1_oid_info_from_oid(x509_ext_ids, x509_ext_ids_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +// 不同于X509算法,X509扩展的数量比较多,而且很多没有在RFC中,而是由某些大公司给出的, 因此这个函数接口要返回nodes +int x509_ext_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + const ASN1_OID_INFO *info; + + *oid = 0; + if ((ret = asn1_oid_info_from_der_ex(&info, nodes, nodes_cnt, x509_ext_ids, x509_ext_ids_count, in, inlen)) != 1) { + error_print(); + return -1; + } + *oid = info->oid; + return ret; +} + + +static uint32_t oid_qt_cps[] = { oid_qt,1 }; +static uint32_t oid_qt_unotice[] = {oid_qt,2 }; + +static const ASN1_OID_INFO x509_qt_ids[] = { + { OID_qt_cps, "CPS", oid_qt_cps, sizeof(oid_qt_cps)/sizeof(int) }, + { OID_qt_unotice, "userNotice", oid_qt_unotice, sizeof(oid_qt_unotice)/sizeof(int) } +}; + +static const int x509_qt_ids_count = + sizeof(x509_qt_ids)/sizeof(x509_qt_ids[0]); + +int x509_qualifier_id_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_qt_ids, x509_qt_ids_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +const char *x509_qualifier_id_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_qt_ids, x509_qt_ids_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +int x509_qualifier_id_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_qt_ids, x509_qt_ids_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_qualifier_id_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + if ((ret = asn1_oid_info_from_der(&info, x509_qt_ids, x509_qt_ids_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + *oid = info->oid; + return 1; +} + + +static uint32_t oid_any_policy[] = { oid_ce,32,0 }; + +int x509_cert_policy_id_to_der(int oid, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen) +{ + switch (oid) { + case OID_any_policy: + if (asn1_object_identifier_to_der(oid_any_policy, sizeof(oid_any_policy)/sizeof(int), out, outlen) != 1) { + error_print(); + return -1; + } + break; + case OID_undef: + if (asn1_object_identifier_to_der(nodes, nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_cert_policy_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen) +{ + int ret; + *oid = OID_undef; + if ((ret = asn1_object_identifier_from_der(nodes, nodes_cnt, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*nodes_cnt == sizeof(oid_any_policy)/sizeof(int) + && memcmp(nodes, oid_any_policy, sizeof(oid_any_policy))) { + *oid = OID_any_policy; + } + return 1; +} + +int x509_cert_policy_id_from_name(const char *name) +{ + if (strcmp(name, "anyPolicy") == 0) { + return OID_any_policy; + } + return OID_undef; +} + +char *x509_cert_policy_id_name(int oid) +{ + switch (oid) { + case OID_any_policy: return "anyPolicy"; + } + return NULL; +} + + + +#define oid_kp oid_pkix,3 + +static uint32_t oid_kp_server_auth[] = { oid_kp,1 }; +static uint32_t oid_kp_client_auth[] = { oid_kp,2 }; +static uint32_t oid_kp_code_signing[] = { oid_kp,3 }; +static uint32_t oid_kp_email_protection[] = { oid_kp,4 }; +static uint32_t oid_kp_time_stamping[] = { oid_kp,8 }; +static uint32_t oid_kp_ocsp_signing[] = { oid_kp,9 }; + + +static const ASN1_OID_INFO x509_key_purposes[] = { + { OID_kp_server_auth, "serverAuth", oid_kp_server_auth, 9, 0, "TLS WWW server authentication" }, + { OID_kp_client_auth, "clientAuth", oid_kp_client_auth, 9, 0, "TLS WWW client authentication" }, + { OID_kp_code_signing, "codeSigning", oid_kp_code_signing, 9, 0, "Signing of downloadable executable code" }, + { OID_kp_email_protection, "emailProtection", oid_kp_email_protection, 9, 0, "Email protection" }, + { OID_kp_time_stamping, "timeStamping", oid_kp_time_stamping, 9, 0, "Binding the hash of an object to a time" }, + { OID_kp_ocsp_signing, "OCSPSigning", oid_kp_ocsp_signing, 9, 0, "Signing OCSP responses" }, +}; + +static const int x509_key_purposes_count = + sizeof(x509_key_purposes)/sizeof(x509_key_purposes[0]); + +int x509_key_purpose_from_name(const char *name) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_name(x509_key_purposes, x509_key_purposes_count, name))) { + error_print(); + return OID_undef; + } + return info->oid; +} + +const char *x509_key_purpose_name(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_key_purposes, x509_key_purposes_count, oid))) { + error_print(); + return NULL; + } + return info->name; +} + +const char *x509_key_purpose_text(int oid) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_key_purposes, x509_key_purposes_count, oid))) { + error_print(); + return NULL; + } + return info->description; +} + +int x509_key_purpose_to_der(int oid, uint8_t **out, size_t *outlen) +{ + const ASN1_OID_INFO *info; + if (!(info = asn1_oid_info_from_oid(x509_key_purposes, x509_key_purposes_count, oid))) { + error_print(); + return -1; + } + if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_key_purpose_from_der(int *oid, const uint8_t **in, size_t *inlen) +{ + int ret; + const ASN1_OID_INFO *info; + + if ((ret = asn1_oid_info_from_der(&info, x509_key_purposes, x509_key_purposes_count, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + *oid = info->oid; + return 1; +} diff --git a/src/x509_prn.c b/src/x509_prn.c new file mode 100644 index 00000000..d518db8f --- /dev/null +++ b/src/x509_prn.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int x509_other_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + uint32_t nodes[32]; + size_t nodes_count; + const uint8_t *value; + size_t valuelen; + + format_print(fp, fmt, ind, "%s:\n", label); + ind += 4; + if (asn1_object_identifier_from_der(nodes, &nodes_count, &d, &dlen) != 1 + || asn1_explicit_from_der(0, &value, &valuelen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + asn1_oid_nodes_print(fp, fmt, ind, "type-id", "unknown", nodes, nodes_count); + format_bytes(fp, fmt, ind, "value: ", value, valuelen); + return 1; +} + +int x509_edi_party_name_print(FILE *fp, int fmt, int ind, const char *label,const uint8_t *d, size_t dlen) +{ + const uint8_t *name_assigner; + const uint8_t *party_name; + size_t name_assigner_len, party_name_len; + + format_print(fp, fmt, ind, "%s:\n", label); + ind += 4; + if (asn1_explicit_from_der(0, &name_assigner, &name_assigner_len, &d, &dlen) < 0 + || asn1_explicit_from_der(1, &party_name, &party_name_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (name_assigner) { + if (x509_directory_string_print(fp, fmt, ind, "nameAssigner", + name_assigner, name_assigner_len) != 1) { + error_print(); + return -1; + } + } + if (x509_directory_string_print(fp, fmt, ind, "partyName", party_name, party_name_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_general_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + switch (tag) { + case ASN1_TAG_IMPLICIT(0): return x509_other_name_print(fp, fmt, ind, "otherName", d, dlen); + case ASN1_TAG_IMPLICIT(1): return asn1_string_print(fp, fmt, ind, "rfc822Name", (char *)d, dlen); + case ASN1_TAG_IMPLICIT(2): return asn1_string_print(fp, fmt, ind, "DNSName", (char *)d, dlen); + case ASN1_TAG_IMPLICIT(3): return format_bytes(fp, fmt, ind, "x400Address", d, dlen); + case ASN1_TAG_IMPLICIT(4): return x509_name_print(fp, fmt, ind, "directoryName", d, dlen); + case ASN1_TAG_IMPLICIT(5): return x509_edi_party_name_print(fp, fmt, ind, "ediPartyName", d, dlen); + case ASN1_TAG_IMPLICIT(6): return asn1_string_print(fp, fmt, ind, "URI", (char *)d, dlen); + case ASN1_TAG_IMPLICIT(7): return format_bytes(fp, fmt, ind, "IPAddress", d, dlen); + case ASN1_TAG_IMPLICIT(8): return asn1_object_identifier_print(fp, fmt, ind, "registeredID", d, dlen); + default: + error_print(); + return -1; + } + return 1; +} + +int x509_general_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + int tag; + const uint8_t *p; + size_t len; + if (asn1_any_type_from_der(&tag, &p, &len, &d, &dlen) != 1 + || x509_general_name_print(fp, fmt, ind, NULL, tag, p, len) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int usage; + if (asn1_bits_from_der(&usage, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "keyUsage:\n"); + ind += 4; + + if (usage & X509_KU_DIGITAL_SIGNATURE) + format_print(fp, fmt, ind, "DigitalSignature\n"); + if (usage & X509_KU_NON_REPUDIATION) + format_print(fp, fmt, ind, "NonRepudiation\n"); + if (usage & X509_KU_KEY_ENCIPHERMENT) + format_print(fp, fmt, ind, "KeyEncipherment\n"); + if (usage & X509_KU_DATA_ENCIPHERMENT) + format_print(fp, fmt, ind, "DataEncipherment\n"); + if (usage & X509_KU_KEY_AGREEMENT) + format_print(fp, fmt, ind, "KeyAgreement\n"); + if (usage & X509_KU_KEY_CERT_SIGN) + format_print(fp, fmt, ind, "KeyCertSign\n"); + if (usage & X509_KU_CRL_SIGN) + format_print(fp, fmt, ind, "CRLSign\n"); + if (usage & X509_KU_ENCIPHER_ONLY) + format_print(fp, fmt, ind, "EncipherOnly\n"); + if (usage & X509_KU_DECIPHER_ONLY) + format_print(fp, fmt, ind, "DecipherOnly\n"); + + + return 1; +} + +int x509_authority_key_identifier_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *keyid, *issuer, *serial; + size_t keyid_len, issuer_len, serial_len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_implicit_octet_string_from_der(0, &keyid, &keyid_len, &d, &dlen) < 0 + || asn1_implicit_sequence_from_der(1, &issuer, &issuer_len, &d, &dlen) < 0 + || asn1_implicit_integer_from_der(2, &serial, &serial_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (keyid) { + format_bytes(fp, fmt, ind, "keyIdentifier : ", keyid, keyid_len); + } + if (issuer) { + x509_general_names_print(fp, fmt, ind, "authorityCertIssuer", issuer, issuer_len); + } + if (serial) { + format_bytes(fp, fmt, ind, "authorityCertSerialNumber", serial, serial_len); + } + return 1; +} + + + +int x509_policy_information_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if (asn1_object_identifier_from_der(nodes, &nodes_cnt, &d, &dlen) != 1) goto err; + + + return 1; +} + +int x509_certificate_policies_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + const uint8_t *p; + size_t len; + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_policy_information_print(fp, fmt, ind, "PolicyInformation", p, len) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_policy_mapping_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return 1; +} + +int x509_policy_mappings_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + const uint8_t *p; + size_t len; + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1 + || x509_policy_mapping_print(fp, fmt, ind, "PolicyMapping", p, len) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_attribute_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return 1; +} + +int x509_attributes_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + const uint8_t *p; + size_t len; + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1 + || x509_attribute_print(fp, fmt, ind, "Attribute", p, len) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + int val; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + + if ((ret = asn1_boolean_from_der(&val, &d, &dlen)) < 0) goto err; + else if (ret) + format_print(fp, fmt, ind, "cA: %s\n", val ? "true" : "false"); + + if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; + else if (ret) + format_print(fp, fmt, ind, "pathLenConstraint: %d\n", val); + + return 1; +err: + error_print(); + return -1; +} + +int x509_general_subtree_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + int val; + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if (asn1_any_type_from_der(&val, &p, &len, &d, &dlen) != 1) goto err; + if (x509_general_name_print(fp, fmt, ind, "base", val, p, len) != 1) goto err; + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "minimum: %d\n", val); + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "maximum: %d\n", val); + if (dlen) { + format_bytes(fp, fmt, ind, "", d, dlen); + goto err; + } + return 1; +err: + error_print(); + return -1; +} + +int x509_general_subtrees_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + const uint8_t *p; + size_t len; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1 + || x509_general_subtree_print(fp, fmt, ind, "GeneralSubtree", p, len) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_name_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) { + x509_general_subtrees_print(fp, fmt, ind, "permittedSubtrees", p, len); + } + + if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err; + if (ret) { + x509_general_subtrees_print(fp, fmt, ind, "excludedSubtrees", p, len); + } + if (dlen) { + } + + return 1; +err: + error_print(); + return -1; +} + +int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + int val; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "requireExplicitPolicy: %d\n", val); + if ((ret = asn1_implicit_int_from_der(0, &val, &d, &dlen)) < 0) goto err; + if (ret) format_print(fp, fmt, ind, "inhibitPolicyMapping: %d\n", val); + if (dlen) { + format_bytes(fp, fmt, ind, "", d, dlen); + goto err; + } + return 1; +err: + error_print(); + return -1; +} + +int x509_ext_key_usage_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + int oid; + if (x509_key_purpose_from_der(&oid, &d, &dlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "%s\n", x509_key_purpose_name(oid)); + } + return 1; +} + +int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return -1; +} + +int x509_reason_flags_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + return -1; +} + +int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret; + int val; + const uint8_t *p; + size_t len; + + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + if ((ret = asn1_explicit_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) { + if (x509_distribution_point_name_print(fp, fmt, ind, "distributionPoint", p, len) != 1) { + error_print(); + return -1; + } + } + + if ((ret = asn1_implicit_bits_from_der(1, &val, &d, &dlen)) < 0) goto err; + if (ret) { + x509_reason_flags_print(fp, fmt, ind, "reasons", p, len); + } + + if ((ret = asn1_implicit_sequence_from_der(2, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) { + x509_general_names_print(fp, fmt, ind, "cRLIssuer", p, len); + } + if (dlen) { + format_bytes(fp, fmt, ind, "", d, dlen); + goto err; + } + return 1; + +err: + error_print(); + return -1; +} + +int x509_crl_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + while (dlen) { + const uint8_t *p; + size_t len; + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_distribution_point_print(fp, fmt, ind, "DistributionPoint", p, len) != 1) { + error_print(); + return -1; + } + } + return 1; +} + + +int x509_directory_string_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) +{ + if (label) { + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + } + return -1; +} diff --git a/src/x509_req.c b/src/x509_req.c new file mode 100644 index 00000000..859b8a7c --- /dev/null +++ b/src/x509_req.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int x509_request_info_to_der( + int version, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *attrs, size_t attrs_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (version != X509_version_v1) { + error_print(); + return -1; + } + if (asn1_int_to_der(version, NULL, &len) != 1 + || asn1_sequence_to_der(subject, subject_len, NULL, &len) != 1 + || x509_public_key_info_to_der(subject_public_key, NULL, &len) != 1 + || asn1_implicit_set_to_der(0, attrs, attrs_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || asn1_sequence_to_der(subject, subject_len, out, outlen) != 1 + || x509_public_key_info_to_der(subject_public_key, out, outlen) != 1 + || asn1_implicit_set_to_der(0, attrs, attrs_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_request_info_from_der( + int *version, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **attrs, size_t *attrs_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || asn1_sequence_from_der(subject, subject_len, &d, &dlen) != 1 + || x509_public_key_info_from_der(subject_public_key, &d, &dlen) != 1 + || asn1_implicit_set_from_der(0, attrs, attrs_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (*version != X509_version_v1) { + error_print(); + return -1; + } + return 1; +} + +int x509_request_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + int ret, ival; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&ival, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %s (%d)\n", x509_version_name(ival), ival); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_name_print(fp, fmt, ind, "subject", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_public_key_info_print(fp, fmt, ind, "subjectPublicKeyInfo", p, len); + if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_attributes_print(fp, fmt, ind, "attributes", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_request_to_der( + int version, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *attrs, size_t attrs_len, + int signature_algor, + const uint8_t *sig, size_t siglen, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (x509_request_info_to_der(version, subject, subject_len, subject_public_key, attrs, attrs_len, NULL, &len) != 1 + || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_request_info_to_der(version, subject, subject_len, subject_public_key, attrs, attrs_len, out, outlen) != 1 + || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_request_from_der( + int *version, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **attrs, size_t *attrs_len, + int *signature_algor, + const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_request_info_from_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, &d, &dlen) != 1 + || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 + || asn1_bit_octets_from_der(sig, siglen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_request_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_request_info_print(fp, fmt, ind, "certificationRequestInfo", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "signature: ", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + +int x509_req_sign( + uint8_t *req, size_t *reqlen, size_t maxlen, + int version, + const uint8_t *subject, size_t subject_len, + const SM2_KEY *subject_public_key, + const uint8_t *attrs, size_t attrs_len, + int signature_algor, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len) +{ + uint8_t req_info[2048]; + size_t req_info_len = 0; + uint8_t *p = req_info; + size_t len = 0; + SM2_SIGN_CTX sign_ctx; + uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + if (x509_request_info_to_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, NULL, &len) != 1 + || asn1_length_le(len, sizeof(req_info)) != 1 + || x509_request_info_to_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, &p, &req_info_len) != 1) { + error_print(); + return -1; + } + + if (signature_algor != OID_sm2sign_with_sm3) { + error_print(); + return -1; + } + if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 + || sm2_sign_update(&sign_ctx, req_info, req_info_len) != 1 + || sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) { + memset(&sign_ctx, 0, sizeof(sign_ctx)); + error_print(); + return -1; + } + memset(&sign_ctx, 0, sizeof(sign_ctx)); + + len = *reqlen = 0; + if (x509_request_to_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, signature_algor, sig, siglen, NULL, &len) != 1 + || asn1_length_le(len, maxlen) != 1 + || x509_request_to_der(version, subject, subject_len, subject_public_key, + attrs, attrs_len, signature_algor, sig, siglen, &req, reqlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_req_verify(const uint8_t *req, size_t reqlen, const SM2_KEY *sign_pubkey, const char *signer_id, size_t signer_id_len) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *p; + size_t len; + const uint8_t *req_info; + size_t req_info_len; + int signature_algor; + const uint8_t *sig; + size_t siglen; + SM2_SIGN_CTX sign_ctx; + + if (asn1_sequence_from_der(&d, &dlen, &req, &reqlen) != 1 + || asn1_length_is_zero(reqlen) != 1) { + error_print(); + return -1; + } + + req_info = d; + req_info_len = dlen; + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + req_info_len -= dlen; + + if (x509_signature_algor_from_der(&signature_algor, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&sig, &siglen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (signature_algor != OID_sm2sign_with_sm3) { + error_print(); + return -1; + } + if (sm2_verify_init(&sign_ctx, sign_pubkey, signer_id, signer_id_len) != 1 + || sm2_verify_update(&sign_ctx, req_info, req_info_len) != 1 + || (ret = sm2_verify_finish(&sign_ctx, sig, siglen)) != 1) { + error_print(); + return -1; + } + return ret; +} + +int x509_req_get_details(const uint8_t *req, size_t reqlen, + int *version, + const uint8_t **subject, size_t *subject_len, + SM2_KEY *subject_public_key, + const uint8_t **attributes, size_t *attributes_len, + int *signature_algor, + const uint8_t **signature, size_t *signature_len) +{ + int ver; + const uint8_t *subj; + size_t subj_len; + SM2_KEY pub_key; + const uint8_t *attrs; + size_t attrs_len; + int sig_alg; + const uint8_t *sig; + size_t siglen; + + if (x509_request_from_der(&ver, &subj, &subj_len, &pub_key, &attrs, &attrs_len, + &sig_alg, &sig, &siglen, &req, &reqlen) != 1 + || asn1_length_is_zero(reqlen) != 1) { + error_print(); + return -1; + } + if (version) *version = ver; + if (subject) *subject = subj; + if (subject_len) *subject_len = subj_len; + if (subject_public_key) *subject_public_key = pub_key; + if (attributes) *attributes = attrs; + if (attributes_len) *attributes_len = attrs_len; + if (signature_algor) *signature_algor = sig_alg; + if (signature) *signature = sig; + if (signature_len) *signature_len = siglen; + return 1; +} + +int x509_req_print(FILE *fp, int fmt, int ind, const uint8_t *req, size_t reqlen) +{ + const uint8_t *d; + size_t dlen; + + if (asn1_sequence_from_der(&d, &dlen, &req, &reqlen) != 1 + || asn1_length_is_zero(reqlen) != 1) { + error_print(); + return -1; + } + x509_request_print(fp, fmt, ind, "CertificationRequest", d, dlen); + return 1; +} + +int x509_req_to_pem(const uint8_t *req, size_t reqlen, FILE *fp) +{ + if (pem_write(fp, "CERTIFICATE REQUEST", req, reqlen) <= 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_req_from_pem(uint8_t *req, size_t *reqlen, size_t maxlen, FILE *fp) +{ + if (pem_read(fp, "CERTIFICATE REQUEST", req, reqlen, maxlen) != 1) { + error_print(); + return -1; + } + return 1; +} diff --git a/src/x509_str.c b/src/x509_str.c new file mode 100644 index 00000000..6b084357 --- /dev/null +++ b/src/x509_str.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +DirectoryString ::= CHOICE { + teletexString TeletexString (SIZE (1..MAX)), + printableString PrintableString (SIZE (1..MAX)), + universalString UniversalString (SIZE (1..MAX)), + utf8String UTF8String (SIZE (1..MAX)), + bmpString BMPString (SIZE (1..MAX)) } + +BMPString has zeros! + "Cert" in BMPStirng is 00 43 00 65 00 72 00 74 + +RDN 中很多值都是这个类型,但是有特定的长度限制,因此这个函数应该增加一个长度限制选项。 +*/ + + +int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen) +{ + switch (tag) { + case ASN1_TAG_TeletexString: + case ASN1_TAG_PrintableString: + case ASN1_TAG_UniversalString: + case ASN1_TAG_UTF8String: + if (d && strnlen((char *)d, dlen) != dlen) { + error_print(); + return -1; + } + break; + case ASN1_TAG_BMPString: + if (d && dlen % 2) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen) +{ + if (x509_directory_name_check(tag, d, dlen) != 1) { + error_print(); + return -1; + } + if (dlen < minlen || dlen > maxlen) { + error_print(); + return -1; + } + return 1; +} + +int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + if (x509_directory_name_check(tag, d, dlen) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(tag, d, dlen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_tag_get(tag, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + switch (*tag) { + case ASN1_TAG_TeletexString: + case ASN1_TAG_PrintableString: + case ASN1_TAG_UniversalString: + case ASN1_TAG_UTF8String: + case ASN1_TAG_BMPString: + break; + default: + return 0; + } + + if ((ret = asn1_any_type_from_der(tag, d, dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_directory_name_check(*tag, *d, *dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + size_t len = 0; + + if ((ret = x509_directory_name_to_der(tag, d, dlen, NULL, &len)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || x509_directory_name_to_der(tag, d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_directory_name_from_der(tag, d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen) +{ + return asn1_string_print(fp, fmt, ind, label, tag, d, dlen); +} + +int x509_display_text_check(int tag, const uint8_t *d, size_t dlen) +{ + switch (tag) { + case ASN1_TAG_IA5String: + case ASN1_TAG_VisibleString: + case ASN1_TAG_UTF8String: + if (d && strnlen((char *)d, dlen) != dlen) { + error_print(); + return -1; + } + break; + case ASN1_TAG_BMPString: + if (d && dlen % 2) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + if (dlen < X509_DISPLAY_TEXT_MIN_LEN || dlen > X509_DISPLAY_TEXT_MAX_LEN) { + error_print(); + return -1; + } + return 1; +} + +int x509_display_text_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + if (x509_display_text_check(tag, d, dlen) != 1) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(tag, d, dlen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + +int x509_display_text_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + + if ((ret = asn1_tag_get(tag, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + switch (*tag) { + case ASN1_TAG_IA5String: + case ASN1_TAG_VisibleString: + case ASN1_TAG_UTF8String: + case ASN1_TAG_BMPString: + break; + default: + return 0; + } + + if ((ret = asn1_any_type_from_der(tag, d, dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_display_text_check(*tag, *d, *dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_display_text_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen) +{ + return asn1_string_print(fp, fmt, ind, label, tag, d, dlen); +} diff --git a/src/zuc_core.c b/src/zuc_core.c index 068760c9..7b529f07 100644 --- a/src/zuc_core.c +++ b/src/zuc_core.c @@ -182,7 +182,7 @@ static const uint8_t S1[256] = { (X0 ^ R1) + R2; \ F_(X1, X2) -void zuc_set_key(ZUC_KEY *key, const unsigned char *user_key, const unsigned char *iv) +void zuc_init(ZUC_STATE *key, const uint8_t *user_key, const uint8_t *iv) { ZUC_UINT31 *LFSR = key->LFSR; uint32_t R1, R2; @@ -211,7 +211,7 @@ void zuc_set_key(ZUC_KEY *key, const unsigned char *user_key, const unsigned cha key->R2 = R2; } -uint32_t zuc_generate_keyword(ZUC_KEY *key) +uint32_t zuc_generate_keyword(ZUC_STATE *key) { ZUC_UINT31 *LFSR = key->LFSR; uint32_t R1 = key->R1; @@ -230,7 +230,7 @@ uint32_t zuc_generate_keyword(ZUC_KEY *key) return Z; } -void zuc_generate_keystream(ZUC_KEY *key, size_t nwords, uint32_t *keystream) +void zuc_generate_keystream(ZUC_STATE *key, size_t nwords, uint32_t *keystream) { ZUC_UINT31 *LFSR = key->LFSR; uint32_t R1 = key->R1; @@ -249,14 +249,14 @@ void zuc_generate_keystream(ZUC_KEY *key, size_t nwords, uint32_t *keystream) key->R2 = R2; } -void zuc_mac_init(ZUC_MAC_CTX *ctx, const unsigned char key[16], const unsigned char iv[16]) +void zuc_mac_init(ZUC_MAC_CTX *ctx, const uint8_t key[16], const uint8_t iv[16]) { memset(ctx, 0, sizeof(*ctx)); - zuc_set_key((ZUC_KEY *)ctx, key, iv); - ctx->K0 = zuc_generate_keyword((ZUC_KEY *)ctx); + zuc_init((ZUC_STATE *)ctx, key, iv); + ctx->K0 = zuc_generate_keyword((ZUC_STATE *)ctx); } -void zuc_mac_update(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t len) +void zuc_mac_update(ZUC_MAC_CTX *ctx, const uint8_t *data, size_t len) { ZUC_UINT32 T = ctx->T; ZUC_UINT32 K0 = ctx->K0; @@ -331,7 +331,7 @@ void zuc_mac_update(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t len) ctx->T = T; } -void zuc_mac_finish(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char mac[4]) +void zuc_mac_finish(ZUC_MAC_CTX *ctx, const uint8_t *data, size_t nbits, uint8_t mac[4]) { ZUC_UINT32 T = ctx->T; ZUC_UINT32 K0 = ctx->K0; @@ -393,7 +393,7 @@ void zuc_mac_finish(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t nbits, u } -typedef unsigned char ZUC_UINT7; +typedef uint8_t ZUC_UINT7; static const ZUC_UINT7 ZUC256_D[][16] = { {0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40, @@ -413,8 +413,8 @@ static const ZUC_UINT7 ZUC256_D[][16] = { (uint32_t)(d)) -static void zuc256_set_mac_key(ZUC_KEY *key, const unsigned char K[32], - const unsigned char IV[23], int macbits) +static void zuc256_set_mac_key(ZUC_STATE *key, const uint8_t K[32], + const uint8_t IV[23], int macbits) { ZUC_UINT31 *LFSR = key->LFSR; uint32_t R1, R2; @@ -467,27 +467,27 @@ static void zuc256_set_mac_key(ZUC_KEY *key, const unsigned char K[32], key->R2 = R2; } -void zuc256_set_key(ZUC_KEY *key, const unsigned char K[32], - const unsigned char IV[23]) +void zuc256_init(ZUC_STATE *key, const uint8_t K[32], + const uint8_t IV[23]) { zuc256_set_mac_key(key, K, IV, 0); } -void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const unsigned char key[32], - const unsigned char iv[23], int macbits) +void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const uint8_t key[32], + const uint8_t iv[23], int macbits) { if (macbits < 32) macbits = 32; else if (macbits > 64) macbits = 128; memset(ctx, 0, sizeof(*ctx)); - zuc256_set_mac_key((ZUC256_KEY *)ctx, key, iv, macbits); - zuc256_generate_keystream((ZUC256_KEY *)ctx, macbits/32, ctx->T); - zuc256_generate_keystream((ZUC256_KEY *)ctx, macbits/32, ctx->K0); + zuc256_set_mac_key((ZUC256_STATE *)ctx, key, iv, macbits); + zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->T); + zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->K0); ctx->macbits = (macbits/32) * 32; } -void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t len) +void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t len) { ZUC_UINT32 K1, M; size_t n = ctx->macbits / 32; @@ -509,7 +509,7 @@ void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t le M = GETU32(ctx->buf); ctx->buflen = 0; - K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx); + K1 = zuc256_generate_keyword((ZUC256_STATE *)ctx); for (i = 0; i < 32; i++) { if (M & 0x80000000) { @@ -531,7 +531,7 @@ void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t le while (len >= 4) { M = GETU32(data); - K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx); + K1 = zuc256_generate_keyword((ZUC256_STATE *)ctx); for (i = 0; i < 32; i++) { if (M & 0x80000000) { @@ -557,7 +557,7 @@ void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t le } } -void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char *mac) +void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t nbits, uint8_t *mac) { ZUC_UINT32 K1, M; size_t n = ctx->macbits/32; @@ -578,7 +578,7 @@ void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t nb if (ctx->buflen || nbits) { M = GETU32(ctx->buf); - K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx); + K1 = zuc256_generate_keyword((ZUC256_STATE *)ctx); for (i = 0; i < ctx->buflen * 8 + nbits; i++) { diff --git a/src/zuc_eea.c b/src/zuc_eea.c index 089f1d90..cc3ca54a 100644 --- a/src/zuc_eea.c +++ b/src/zuc_eea.c @@ -50,23 +50,23 @@ #include #include -static void zuc_set_eea_key(ZUC_KEY *key, const unsigned char user_key[16], +static void zuc_set_eea_key(ZUC_STATE *key, const uint8_t user_key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, ZUC_BIT direction) { - unsigned char iv[16] = {0}; + uint8_t iv[16] = {0}; iv[0] = iv[8] = count >> 24; iv[1] = iv[9] = count >> 16; iv[2] = iv[10] = count >> 8; iv[3] = iv[11] = count; iv[4] = iv[12] = ((bearer << 1) | (direction & 1)) << 2; - zuc_set_key(key, user_key, iv); + zuc_init(key, user_key, iv); } void zuc_eea_encrypt(const ZUC_UINT32 *in, ZUC_UINT32 *out, size_t nbits, - const unsigned char key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, + const uint8_t key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, ZUC_BIT direction) { - ZUC_KEY zuc_key; + ZUC_STATE zuc_key; size_t nwords = (nbits + 31)/32; size_t i; diff --git a/src/zuc_eia.c b/src/zuc_eia.c index 73226957..47509e80 100644 --- a/src/zuc_eia.c +++ b/src/zuc_eia.c @@ -52,7 +52,7 @@ #include #include "endian.h" -static void zuc_set_eia_iv(unsigned char iv[16], ZUC_UINT32 count, ZUC_UINT5 bearer, +static void zuc_set_eia_iv(uint8_t iv[16], ZUC_UINT32 count, ZUC_UINT5 bearer, ZUC_BIT direction) { memset(iv, 0, 16); @@ -67,15 +67,15 @@ static void zuc_set_eia_iv(unsigned char iv[16], ZUC_UINT32 count, ZUC_UINT5 bea #if 1 ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits, - const unsigned char key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, + const uint8_t key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, ZUC_BIT direction) { ZUC_MAC_CTX ctx; - unsigned char iv[16]; - unsigned char mac[4]; + uint8_t iv[16]; + uint8_t mac[4]; zuc_set_eia_iv(iv, count, bearer, direction); zuc_mac_init(&ctx, key, iv); - zuc_mac_finish(&ctx, (unsigned char *)data, nbits, mac); + zuc_mac_finish(&ctx, (uint8_t *)data, nbits, mac); return GETU32(mac); } #else @@ -91,12 +91,12 @@ ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits, (((*((ZUC_UINT32 *)(p) + (i)/32)) & (1 << (31 - ((i) % 32)))) ? 1 : 0) ZUC_UINT32 ZUC_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits, - const unsigned char user_key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, + const uint8_t user_key[16], ZUC_UINT32 count, ZUC_UINT5 bearer, ZUC_BIT direction) { ZUC_UINT32 T = 0; - ZUC_KEY key; - unsigned char iv[16]; + ZUC_STATE key; + uint8_t iv[16]; ZUC_UINT32 buf[ZUC_MAC_BUF_WORDS + 2]; size_t nwords = (nbits + 31)/32; size_t i;