mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-11-14 16:45:00 +08:00
Update src
This commit is contained in:
@@ -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,
|
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,
|
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;
|
const uint8_t *pin = in;
|
||||||
uint8_t *pout = out;
|
uint8_t *pout = out;
|
||||||
|
|||||||
474
src/asn1.c
474
src/asn1.c
@@ -59,6 +59,9 @@
|
|||||||
#include "endian.h"
|
#include "endian.h"
|
||||||
|
|
||||||
|
|
||||||
|
//FIXME: ENUMERATED 没有支持,在CRLReason中用到
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
## 返回值
|
## 返回值
|
||||||
@@ -131,7 +134,7 @@ const char *asn1_tag_name(int tag)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int asn1_tag_is_cstring(int tag)
|
int asn1_tag_is_cstring(int tag)
|
||||||
{
|
{
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case ASN1_TAG_UTF8String:
|
case ASN1_TAG_UTF8String:
|
||||||
@@ -167,15 +170,16 @@ int asn1_ia5_string_check(const char *a, size_t alen)
|
|||||||
// 还是检查报错比较方便,这样调用的函数更容易实现
|
// 还是检查报错比较方便,这样调用的函数更容易实现
|
||||||
// asn.1编解码不考虑效率的问题
|
// 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) {
|
if (out) {
|
||||||
*(*out)++ = (uint8_t)tag;
|
*(*out)++ = (uint8_t)tag;
|
||||||
}
|
}
|
||||||
(*outlen)++;
|
(*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 (len < 128) {
|
||||||
if (out) {
|
if (out) {
|
||||||
@@ -200,15 +204,18 @@ void asn1_length_to_der(size_t len, uint8_t **out, size_t *outlen)
|
|||||||
}
|
}
|
||||||
(*outlen) += 1 + i;
|
(*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) {
|
if (out) {
|
||||||
memcpy(*out, data, datalen);
|
memcpy(*out, data, datalen);
|
||||||
*out += datalen;
|
*out += datalen;
|
||||||
}
|
}
|
||||||
*outlen += datalen;
|
*outlen += datalen;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int asn1_tag_from_der(int tag, const uint8_t **in, size_t *inlen)
|
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;
|
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)
|
int asn1_length_from_der(size_t *plen, const uint8_t **pin, size_t *pinlen)
|
||||||
{
|
{
|
||||||
const uint8_t *in = *pin;
|
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;
|
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)
|
int asn1_any_tag_from_der(int *tag, const uint8_t **in, size_t *inlen)
|
||||||
{
|
{
|
||||||
if (*inlen == 0) {
|
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;
|
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 asn1_any_from_der(const uint8_t **tlv, size_t *tlvlen, const uint8_t **in, size_t *inlen)
|
||||||
{
|
{
|
||||||
int ret;
|
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)
|
int asn1_boolean_to_der_ex(int tag, int val, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
if ((out && !(*out)) || !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;
|
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)
|
int asn1_bits_to_der_ex(int tag, int bits, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
size_t nbits = 0;
|
size_t nbits = 0;
|
||||||
@@ -534,7 +543,122 @@ int asn1_null_to_der(uint8_t **out, size_t *outlen)
|
|||||||
return 1;
|
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];
|
uint8_t octets[32];
|
||||||
size_t octetslen = 0;
|
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;
|
*(*out)++ = tag;
|
||||||
(*outlen)++;
|
(*outlen)++;
|
||||||
|
|
||||||
if (oid != OID_undef)
|
asn1_oid_nodes_to_octets(nodes, nodes_cnt, octets, &octetslen);
|
||||||
asn1_oid_to_octets(oid, octets, &octetslen);
|
|
||||||
else asn1_oid_nodes_to_octets(nodes, nodes_count, octets, &octetslen);
|
|
||||||
|
|
||||||
asn1_length_to_der(octetslen, out, outlen);
|
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;
|
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)
|
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;
|
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 asn1_bits_from_der_ex(int tag, int *bits, const uint8_t **in, size_t *inlen)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -836,15 +1050,14 @@ int asn1_null_from_der(const uint8_t **in, size_t *inlen)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME:这个函数应该最终取消返回oid
|
int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_cnt,
|
||||||
int asn1_object_identifier_from_der_ex(int tag, int *oid, uint32_t nodes[32], size_t *nodes_count,
|
|
||||||
const uint8_t **pin, size_t *pinlen)
|
const uint8_t **pin, size_t *pinlen)
|
||||||
{
|
{
|
||||||
const uint8_t *in = *pin;
|
const uint8_t *in = *pin;
|
||||||
size_t inlen = *pinlen;
|
size_t inlen = *pinlen;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (!nodes || !nodes_count || !pin || !(*pin) || !pinlen) {
|
if (!nodes || !nodes_cnt || !pin || !(*pin) || !pinlen) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -858,14 +1071,10 @@ int asn1_object_identifier_from_der_ex(int tag, int *oid, uint32_t nodes[32], si
|
|||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// 由于 asn1_oid_from_der 无法判断不识别的 OID 数据编码是否正确,因此必须先解码
|
if (asn1_object_identifier_from_octets(nodes, nodes_cnt, in, len) != 1) {
|
||||||
if (asn1_oid_nodes_from_octets(nodes, nodes_count, in, len) < 0) {
|
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (oid) {
|
|
||||||
*oid = asn1_oid_from_octets(in, len);
|
|
||||||
}
|
|
||||||
*pin = in + len;
|
*pin = in + len;
|
||||||
*pinlen = inlen - len;
|
*pinlen = inlen - len;
|
||||||
return 1;
|
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;
|
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)
|
int asn1_check(int expr)
|
||||||
{
|
{
|
||||||
@@ -1068,8 +1236,146 @@ int asn1_check(int expr)
|
|||||||
int asn1_length_is_zero(size_t len)
|
int asn1_length_is_zero(size_t len)
|
||||||
{
|
{
|
||||||
if (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();
|
error_print();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 = {
|
static const BLOCK_CIPHER sm4_block_cipher_object = {
|
||||||
|
OID_sm4,
|
||||||
SM4_KEY_SIZE,
|
SM4_KEY_SIZE,
|
||||||
SM4_BLOCK_SIZE,
|
SM4_BLOCK_SIZE,
|
||||||
(block_cipher_set_encrypt_key_func)sm4_set_encrypt_key,
|
(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 = {
|
static const BLOCK_CIPHER aes128_block_cipher_object = {
|
||||||
|
OID_aes128,
|
||||||
AES128_KEY_SIZE,
|
AES128_KEY_SIZE,
|
||||||
AES_BLOCK_SIZE,
|
AES_BLOCK_SIZE,
|
||||||
(block_cipher_set_encrypt_key_func)aes128_set_encrypt_key,
|
(block_cipher_set_encrypt_key_func)aes128_set_encrypt_key,
|
||||||
|
|||||||
@@ -54,8 +54,8 @@
|
|||||||
#include "endian.h"
|
#include "endian.h"
|
||||||
|
|
||||||
void chacha20_set_key(CHACHA20_STATE *state,
|
void chacha20_set_key(CHACHA20_STATE *state,
|
||||||
const unsigned char key[CHACHA20_KEY_SIZE],
|
const uint8_t key[CHACHA20_KEY_SIZE],
|
||||||
const unsigned char nonce[CHACHA20_NONCE_SIZE],
|
const uint8_t nonce[CHACHA20_NONCE_SIZE],
|
||||||
uint32_t counter)
|
uint32_t counter)
|
||||||
{
|
{
|
||||||
state->d[ 0] = 0x61707865;
|
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[2], S[7], S[ 8], S[13]); \
|
||||||
QR(S[3], S[4], S[ 9], S[14])
|
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];
|
uint32_t working_state[16];
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
13
src/debug.c
13
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, ...)
|
int tls_trace(int format, int indent, const char *str, ...)
|
||||||
{
|
{
|
||||||
FILE *fp = stderr;
|
FILE *fp = stderr;
|
||||||
|
|||||||
80
src/digest.c
80
src/digest.c
@@ -53,13 +53,8 @@
|
|||||||
#include <gmssl/digest.h>
|
#include <gmssl/digest.h>
|
||||||
|
|
||||||
|
|
||||||
int digest_nid(const DIGEST *digest)
|
|
||||||
{
|
|
||||||
return digest->nid;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int nid;
|
int oid;
|
||||||
char *short_name;
|
char *short_name;
|
||||||
char *display_name;
|
char *display_name;
|
||||||
} DIGEST_TABLE;
|
} DIGEST_TABLE;
|
||||||
@@ -78,65 +73,44 @@ const char *digest_name(const DIGEST *digest)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < sizeof(digest_table)/sizeof(digest_table[0]); 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 digest_table[i].short_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
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)
|
int digest_init(DIGEST_CTX *ctx, const DIGEST *algor)
|
||||||
{
|
{
|
||||||
|
memset(ctx, 0, sizeof(DIGEST_CTX));
|
||||||
ctx->digest = algor;
|
ctx->digest = algor;
|
||||||
ctx->digest->init(ctx);
|
ctx->digest->init(ctx);
|
||||||
return 1;
|
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);
|
ctx->digest->update(ctx, data, datalen);
|
||||||
return 1;
|
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);
|
ctx->digest->finish(ctx, dgst);
|
||||||
*dgstlen = ctx->digest->digest_size;
|
*dgstlen = ctx->digest->digest_size;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int digest(const DIGEST *digest, const unsigned char *data, size_t datalen,
|
int digest(const DIGEST *digest, const uint8_t *data, size_t datalen,
|
||||||
unsigned char *dgst, size_t *dgstlen)
|
uint8_t *dgst, size_t *dgstlen)
|
||||||
{
|
{
|
||||||
DIGEST_CTX ctx;
|
DIGEST_CTX ctx;
|
||||||
if (!digest_ctx_init(&ctx)
|
if (!digest_init(&ctx, digest)
|
||||||
|| !digest_init(&ctx, digest)
|
|
||||||
|| !digest_update(&ctx, data, datalen)
|
|| !digest_update(&ctx, data, datalen)
|
||||||
|| !digest_finish(&ctx, dgst, dgstlen)) {
|
|| !digest_finish(&ctx, dgst, dgstlen)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
digest_ctx_cleanup(&ctx);
|
memset(&ctx, 0, sizeof(DIGEST_CTX));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +147,7 @@ static int sm3_digest_init(DIGEST_CTX *ctx)
|
|||||||
return 1;
|
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)) {
|
if (!ctx || (!in && inlen != 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -182,7 +156,7 @@ static int sm3_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t in
|
|||||||
return 1;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -218,7 +192,7 @@ static int md5_digest_init(DIGEST_CTX *ctx)
|
|||||||
return 1;
|
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)) {
|
if (!ctx || (!in && inlen != 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -227,7 +201,7 @@ static int md5_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t in
|
|||||||
return 1;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -263,7 +237,7 @@ static int sha1_digest_init(DIGEST_CTX *ctx)
|
|||||||
return 1;
|
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)) {
|
if (!ctx || (!in && inlen != 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -272,7 +246,7 @@ static int sha1_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t i
|
|||||||
return 1;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -308,7 +282,7 @@ static int sha224_digest_init(DIGEST_CTX *ctx)
|
|||||||
return 1;
|
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)) {
|
if (!ctx || (!in && inlen != 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -317,7 +291,7 @@ static int sha224_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t
|
|||||||
return 1;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -350,7 +324,7 @@ static int sha256_digest_init(DIGEST_CTX *ctx)
|
|||||||
return 1;
|
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)) {
|
if (!ctx || (!in && inlen != 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -359,7 +333,7 @@ static int sha256_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t
|
|||||||
return 1;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -393,7 +367,7 @@ static int sha384_digest_init(DIGEST_CTX *ctx)
|
|||||||
return 1;
|
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)) {
|
if (!ctx || (!in && inlen != 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -402,7 +376,7 @@ static int sha384_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t
|
|||||||
return 1;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -436,7 +410,7 @@ static int sha512_digest_init(DIGEST_CTX *ctx)
|
|||||||
return 1;
|
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)) {
|
if (!ctx || (!in && inlen != 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -445,7 +419,7 @@ static int sha512_digest_update(DIGEST_CTX *ctx, const unsigned char *in, size_t
|
|||||||
return 1;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
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) {
|
if (!ctx || !dgst) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ gf128_t gf128_zero(void)
|
|||||||
gf128_t gf128_from_hex(const char *s)
|
gf128_t gf128_from_hex(const char *s)
|
||||||
{
|
{
|
||||||
uint8_t bin[16];
|
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);
|
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 bin1[16];
|
||||||
uint8_t bin2[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);
|
gf128_to_bytes(a, bin2);
|
||||||
return memcmp(bin1, bin2, sizeof(bin1)) == 0;
|
return memcmp(bin1, bin2, sizeof(bin1)) == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,8 +66,6 @@ static int hash_df(const DIGEST *digest, const uint8_t *in, size_t inlen,
|
|||||||
counter = 0x01;
|
counter = 0x01;
|
||||||
PUTU32(outbits, (uint32_t)outlen << 3);
|
PUTU32(outbits, (uint32_t)outlen << 3);
|
||||||
|
|
||||||
digest_ctx_init(&ctx);
|
|
||||||
|
|
||||||
while (outlen > 0) {
|
while (outlen > 0) {
|
||||||
if (!digest_init(&ctx, digest)
|
if (!digest_init(&ctx, digest)
|
||||||
|| !digest_update(&ctx, &counter, sizeof(counter))
|
|| !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;
|
ret = 1;
|
||||||
end:
|
end:
|
||||||
digest_ctx_cleanup(&ctx);
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
memset(dgst, 0, sizeof(dgst));
|
memset(dgst, 0, sizeof(dgst));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -111,7 +109,7 @@ int hash_drbg_init(HASH_DRBG *drbg, const DIGEST *digest,
|
|||||||
drbg->digest = digest;
|
drbg->digest = digest;
|
||||||
|
|
||||||
/* set seedlen */
|
/* set seedlen */
|
||||||
if (digest_size(digest) <= 32) {
|
if (digest->digest_size <= 32) {
|
||||||
drbg->seedlen = HASH_DRBG_SM3_SEED_SIZE;
|
drbg->seedlen = HASH_DRBG_SM3_SEED_SIZE;
|
||||||
} else {
|
} else {
|
||||||
drbg->seedlen = HASH_DRBG_SHA512_SEED_SIZE;
|
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];
|
uint8_t dgst[DIGEST_MAX_SIZE];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
digest_ctx_init(&ctx);
|
|
||||||
|
|
||||||
/* data = V */
|
/* data = V */
|
||||||
memcpy(data, drbg->V, drbg->seedlen);
|
memcpy(data, drbg->V, drbg->seedlen);
|
||||||
|
|
||||||
@@ -289,8 +285,6 @@ int hash_drbg_generate(HASH_DRBG *drbg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
digest_ctx_init(&ctx);
|
|
||||||
|
|
||||||
if (additional) {
|
if (additional) {
|
||||||
/* w = Hash (0x02 || V || additional_input) */
|
/* w = Hash (0x02 || V || additional_input) */
|
||||||
prefix = 0x02;
|
prefix = 0x02;
|
||||||
@@ -336,7 +330,7 @@ int hash_drbg_generate(HASH_DRBG *drbg,
|
|||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
end:
|
end:
|
||||||
digest_ctx_cleanup(&ctx);
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
memset(T, 0, sizeof(T));
|
memset(T, 0, sizeof(T));
|
||||||
memset(dgst, 0, sizeof(dgst));
|
memset(dgst, 0, sizeof(dgst));
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ int hkdf_extract(const DIGEST *digest, const uint8_t *salt, size_t saltlen,
|
|||||||
|
|
||||||
if (!salt || saltlen == 0) {
|
if (!salt || saltlen == 0) {
|
||||||
uint8_t zeros[DIGEST_MAX_SIZE] = {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();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/hmac.c
14
src/hmac.c
@@ -55,7 +55,7 @@
|
|||||||
#define OPAD 0x5C
|
#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 i_key[DIGEST_MAX_BLOCK_SIZE] = {0};
|
||||||
uint8_t o_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;
|
ctx->digest = digest;
|
||||||
|
|
||||||
blocksize = digest_block_size(digest);
|
blocksize = digest->block_size;
|
||||||
if (keylen <= blocksize) {
|
if (keylen <= blocksize) {
|
||||||
memcpy(i_key, key, keylen);
|
memcpy(i_key, key, keylen);
|
||||||
memcpy(o_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;
|
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)) {
|
if (!ctx || (!data && datalen != 0)) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -108,7 +108,7 @@ int hmac_update(HMAC_CTX *ctx, const unsigned char *data, size_t datalen)
|
|||||||
return 1;
|
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) {
|
if (digest_finish(&ctx->digest_ctx, mac, maclen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -140,9 +140,9 @@ int hmac_finish_and_verify(HMAC_CTX *ctx, const uint8_t *mac, size_t maclen)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hmac(const DIGEST *digest, const unsigned char *key, size_t keylen,
|
int hmac(const DIGEST *digest, const uint8_t *key, size_t keylen,
|
||||||
const unsigned char *data, size_t datalen,
|
const uint8_t *data, size_t datalen,
|
||||||
unsigned char *mac, size_t *maclen)
|
uint8_t *mac, size_t *maclen)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
HMAC_CTX ctx;
|
HMAC_CTX ctx;
|
||||||
|
|||||||
361
src/oid.c
361
src/oid.c
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
|
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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);
|
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 "<undef>";
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ int pem_write(FILE *fp, const char *name, const uint8_t *data, size_t datalen)
|
|||||||
return ret;
|
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 line[80];
|
||||||
char begin_line[80];
|
char begin_line[80];
|
||||||
|
|||||||
95
src/pkcs8.c
95
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(
|
int pbkdf2_params_to_der(
|
||||||
const uint8_t *salt, size_t saltlen,
|
const uint8_t *salt, size_t saltlen,
|
||||||
int iter,
|
int iter,
|
||||||
@@ -103,7 +107,7 @@ int pbkdf2_params_to_der(
|
|||||||
if (asn1_octet_string_to_der(salt, saltlen, NULL, &len) != 1
|
if (asn1_octet_string_to_der(salt, saltlen, NULL, &len) != 1
|
||||||
|| asn1_int_to_der(iter, NULL, &len) != 1
|
|| asn1_int_to_der(iter, NULL, &len) != 1
|
||||||
|| asn1_int_to_der(keylen, NULL, &len) < 0
|
|| 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_null_to_der(NULL, &prflen) != 1
|
||||||
|| asn1_sequence_to_der(NULL, prflen, NULL, &len) != 1
|
|| asn1_sequence_to_der(NULL, prflen, NULL, &len) != 1
|
||||||
|| asn1_sequence_header_to_der(len, out, outlen) != 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(iter, out, outlen) != 1
|
||||||
|| asn1_int_to_der(keylen, out, outlen) < 0
|
|| asn1_int_to_der(keylen, out, outlen) < 0
|
||||||
|| asn1_sequence_header_to_der(prflen, out, outlen) != 1
|
|| 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) {
|
|| asn1_null_to_der(out, outlen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -155,16 +159,22 @@ int pbkdf2_params_from_der(
|
|||||||
if (algo) {
|
if (algo) {
|
||||||
uint32_t nodes[32];
|
uint32_t nodes[32];
|
||||||
size_t nodes_count;
|
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
|
|| asn1_null_from_der(&algo, &algolen) != 1
|
||||||
|| algolen > 0) {
|
|| algolen > 0) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
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();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//*prf = OID_hmacWithSHA1;
|
//*prf = OID_hmacWithSHA1;
|
||||||
error_print();
|
error_print();
|
||||||
@@ -174,6 +184,9 @@ int pbkdf2_params_from_der(
|
|||||||
return 1;
|
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(
|
int pbkdf2_algor_to_der(
|
||||||
const uint8_t *salt, size_t saltlen,
|
const uint8_t *salt, size_t saltlen,
|
||||||
int iter,
|
int iter,
|
||||||
@@ -182,13 +195,11 @@ int pbkdf2_algor_to_der(
|
|||||||
uint8_t **out, size_t *outlen)
|
uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
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
|
|| pbkdf2_params_to_der(salt, saltlen, iter, keylen, prf, NULL, &len) != 1
|
||||||
|| asn1_sequence_header_to_der(len, out, outlen) != 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) {
|
|| pbkdf2_params_to_der(salt, saltlen, iter, keylen, prf, out, outlen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -206,8 +217,6 @@ int pbkdf2_algor_from_der(
|
|||||||
int ret;
|
int ret;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
uint32_t pbkdf2[] = { 1, 2, 840, 113549, 1, 5, 12 };
|
|
||||||
size_t pbkdf2_count = sizeof(pbkdf2)/sizeof(pbkdf2[0]);
|
|
||||||
int oid;
|
int oid;
|
||||||
uint32_t nodes[32];
|
uint32_t nodes[32];
|
||||||
size_t nodes_count;
|
size_t nodes_count;
|
||||||
@@ -216,14 +225,15 @@ int pbkdf2_algor_from_der(
|
|||||||
if (ret < 0) error_print();
|
if (ret < 0) error_print();
|
||||||
return ret;
|
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
|
|| pbkdf2_params_from_der(salt, saltlen, iter, keylen, prf, &data, &datalen) != 1
|
||||||
|| datalen > 0) {
|
|| datalen > 0) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (oid != OID_undef || nodes_count != pbkdf2_count
|
if (oid != OID_undef || nodes_count != oid_pbkdf2_count
|
||||||
|| memcmp(nodes, pbkdf2, sizeof(pbkdf2)) != 0) {
|
|| memcmp(nodes, oid_pbkdf2, sizeof(oid_pbkdf2)) != 0) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -232,8 +242,8 @@ int pbkdf2_algor_from_der(
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t sm4_cbc_nodes[] = { 1, 2, 156, 10197, 1, 104, 2 };
|
static const uint32_t oid_sm4_cbc[] = { 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 size_t oid_sm4_cbc_count = sizeof(oid_sm4_cbc)/sizeof(oid_sm4_cbc[0]);
|
||||||
|
|
||||||
|
|
||||||
// 这个应该提取到外面,和digest_algor, encryption_algor, sign_algor 之类的放到一起
|
// 这个应该提取到外面,和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();
|
error_print();
|
||||||
return -1;
|
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_octet_string_to_der(iv, ivlen, NULL, &len) != 1
|
||||||
|| asn1_sequence_header_to_der(len, out, outlen) != 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) {
|
|| asn1_octet_string_to_der(iv, ivlen, out, outlen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
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();
|
if (ret < 0) error_print();
|
||||||
return ret;
|
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
|
|| asn1_octet_string_from_der(iv, ivlen, &data, &datalen) != 1
|
||||||
|| datalen > 0) {
|
|| asn1_length_is_zero(datalen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (*cipher == OID_undef) {
|
|
||||||
if (nodes_count == sm4_cbc_nodes_count
|
if (asn1_object_identifier_equ(nodes, nodes_count, oid_sm4_cbc, oid_sm4_cbc_count) != 1) {
|
||||||
&& memcmp(nodes, sm4_cbc_nodes, sizeof(sm4_cbc_nodes)) == 0) {
|
size_t i;
|
||||||
*cipher = OID_sm4_cbc;
|
*cipher = OID_undef;
|
||||||
} else {
|
error_print();
|
||||||
size_t i;
|
for (i = 0; i < nodes_count; i++) {
|
||||||
error_print();
|
fprintf(stderr, " %d", nodes[i]);
|
||||||
for (i = 0; i < nodes_count; i++) {
|
|
||||||
fprintf(stderr, " %d", nodes[i]);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
*cipher = OID_sm4_cbc;
|
||||||
|
|
||||||
// FIXME: 检查ivlen
|
// FIXME: 检查ivlen
|
||||||
return 1;
|
return 1;
|
||||||
@@ -345,6 +354,10 @@ int pbes2_params_from_der(
|
|||||||
return 1;
|
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(
|
int pbes2_algor_to_der(
|
||||||
const uint8_t *salt, size_t saltlen,
|
const uint8_t *salt, size_t saltlen,
|
||||||
int iter,
|
int iter,
|
||||||
@@ -354,13 +367,11 @@ int pbes2_algor_to_der(
|
|||||||
uint8_t **out, size_t *outlen)
|
uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
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
|
|| pbes2_params_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, NULL, &len) != 1
|
||||||
|| asn1_sequence_header_to_der(len, out, outlen) != 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) {
|
|| pbes2_params_to_der(salt, saltlen, iter, prf, cipher, iv, ivlen, out, outlen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -379,8 +390,6 @@ int pbes2_algor_from_der(
|
|||||||
int ret;
|
int ret;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
uint32_t pbes2[] = { 1, 2, 840, 113549, 1, 5, 13 };
|
|
||||||
size_t pbes2_count = sizeof(pbes2)/sizeof(pbes2[0]);
|
|
||||||
int oid;
|
int oid;
|
||||||
uint32_t nodes[32];
|
uint32_t nodes[32];
|
||||||
size_t nodes_count;
|
size_t nodes_count;
|
||||||
@@ -389,17 +398,15 @@ int pbes2_algor_from_der(
|
|||||||
if (ret < 0) error_print();
|
if (ret < 0) error_print();
|
||||||
return ret;
|
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
|
|| pbes2_params_from_der(salt, saltlen, iter, prf, cipher, iv, ivlen, &data, &datalen) != 1
|
||||||
|| datalen > 0) {
|
|| datalen > 0) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (oid != OID_undef) {
|
if (nodes_count != oid_pbes2_count
|
||||||
error_print();
|
&& memcmp(nodes, oid_pbes2, sizeof(oid_pbes2)) != 0) {
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (nodes_count != pbes2_count && memcmp(nodes, pbes2, sizeof(pbes2)) != 0) {
|
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
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;
|
const uint8_t *attrs;
|
||||||
size_t attrslen;
|
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();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/rc4.c
16
src/rc4.c
@@ -51,12 +51,12 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <gmssl/rc4.h>
|
#include <gmssl/rc4.h>
|
||||||
|
|
||||||
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;
|
int i, j;
|
||||||
unsigned char *s = state->d;
|
uint8_t *s = state->d;
|
||||||
unsigned char k[256];
|
uint8_t k[256];
|
||||||
unsigned char temp;
|
uint8_t temp;
|
||||||
|
|
||||||
/* expand key */
|
/* expand key */
|
||||||
for (i = 0; i < keylen; i++) {
|
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));
|
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;
|
int i = 0, j = 0;
|
||||||
unsigned char *s = state->d;
|
uint8_t *s = state->d;
|
||||||
int oi;
|
int oi;
|
||||||
int temp;
|
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);
|
rc4_generate_keystream(state, 1, out);
|
||||||
return out[0];
|
return out[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1251,13 +1251,13 @@ static int point_test(void)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sm2_algo_selftest(void)
|
int sm2_selftest(void)
|
||||||
{
|
{
|
||||||
point_test();
|
point_test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sm2_keygen(SM2_KEY *key)
|
int sm2_key_generate(SM2_KEY *key)
|
||||||
{
|
{
|
||||||
bignum_t x;
|
bignum_t x;
|
||||||
bignum_t y;
|
bignum_t y;
|
||||||
|
|||||||
116
src/sm2_asn1.c
116
src/sm2_asn1.c
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
|
* Copyright (c) 2014 - 2020 The GmSSL Project. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -53,6 +53,9 @@
|
|||||||
#include <gmssl/pem.h>
|
#include <gmssl/pem.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
// sm2 curve 1.2.156.10197.1.301
|
||||||
|
|
||||||
|
|
||||||
void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33])
|
void sm2_point_to_compressed_octets(const SM2_POINT *P, uint8_t out[33])
|
||||||
{
|
{
|
||||||
*out++ = (P->y[31] & 0x01) ? 0x03 : 0x02;
|
*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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int sm2_ciphertext_size(size_t inlen, size_t *outlen)
|
||||||
SM2Cipher ::= SEQUENCE {
|
{
|
||||||
XCoordinate INTEGER, // 变长
|
*outlen = sizeof(SM2_CIPHERTEXT)-1+inlen;
|
||||||
YCoordinate INTEGER, // 变长
|
return 1;
|
||||||
HASH OCTET STRING SIZE(32),
|
|
||||||
CipherText OCTET STRING
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen)
|
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
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;
|
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 {
|
// TODO: sm2, ecPublicKey 这些公用的OID应该提取到一个地方
|
||||||
namedCurve OBJECT IDENTIFIER
|
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 sm2_private_key_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
int version = 1;
|
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_int_to_der(version, NULL, &len);
|
||||||
asn1_octet_string_to_der(key->private_key, 32, 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_explicit_to_der(0, NULL, params_len, NULL, &len);
|
||||||
asn1_bit_string_to_der(public_key, sizeof(public_key) * 8, NULL, &pubkey_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);
|
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_int_to_der(version, out, outlen);
|
||||||
asn1_octet_string_to_der(key->private_key, 32, out, outlen);
|
asn1_octet_string_to_der(key->private_key, 32, out, outlen);
|
||||||
asn1_explicit_header_to_der(0, params_len, 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_explicit_header_to_der(1, pubkey_len, out, outlen);
|
||||||
asn1_bit_string_to_der(public_key, sizeof(public_key) * 8, 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();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sm2_set_private_key(key, prikey) != 1) {
|
if (sm2_key_set_private_key(key, prikey) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (params) {
|
if (params) {
|
||||||
int curve_oid;
|
uint32_t nodes[16]; // FIXME: 这个长度不对啊!
|
||||||
uint32_t nodes[16];
|
|
||||||
size_t nodes_count;
|
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) {
|
|| params_len > 0) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (curve_oid != OID_sm2) {
|
if (nodes_count != oid_sm2_count
|
||||||
|
|| memcmp(nodes, oid_sm2, sizeof(oid_sm2)) != 0) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -307,19 +297,22 @@ int sm2_private_key_from_der(SM2_KEY *key, const uint8_t **in, size_t *inlen)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
AlgorithmIdentifier ::= {
|
|
||||||
algorithm OBJECT IDENTIFIER { id-ecPublicKey },
|
static const uint32_t oid_ec_public_key[] = { 1,2,840,10045,2,1 };
|
||||||
parameters OBJECT IDENTIFIER { id-sm2 } }
|
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)
|
int sm2_public_key_algor_to_der(uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
asn1_object_identifier_to_der(OID_x9_62_ecPublicKey, NULL, 0, NULL, &len);
|
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, NULL, 0, NULL, &len);
|
|| asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, NULL, &len) != 1
|
||||||
asn1_sequence_header_to_der(len, out, outlen);
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
asn1_object_identifier_to_der(OID_x9_62_ecPublicKey, NULL, 0, out, outlen);
|
|| asn1_object_identifier_to_der(oid_ec_public_key, oid_ec_public_key_count, out, outlen) != 1
|
||||||
asn1_object_identifier_to_der(OID_sm2, NULL, 0, out, outlen);
|
|| asn1_object_identifier_to_der(oid_sm2, oid_sm2_count, out, outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,23 +321,20 @@ int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen)
|
|||||||
int ret;
|
int ret;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
int oid;
|
uint32_t nodes[ASN1_OID_MAX_NODES];
|
||||||
uint32_t nodes[16];
|
size_t nodes_count;
|
||||||
size_t nodes_count = 16;
|
|
||||||
|
|
||||||
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
|
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
|
||||||
if (ret < 0) error_print();
|
if (ret < 0) error_print();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1
|
||||||
if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1
|
|| asn1_object_identifier_equ(nodes, nodes_count, oid_ec_public_key, oid_ec_public_key_count) != 1) {
|
||||||
|| oid != OID_x9_62_ecPublicKey) {
|
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (asn1_object_identifier_from_der(nodes, &nodes_count, &data, &datalen) != 1
|
||||||
if (asn1_object_identifier_from_der(&oid, nodes, &nodes_count, &data, &datalen) != 1
|
|| asn1_object_identifier_equ(nodes, nodes_count, oid_sm2, oid_sm2_count) != 1) {
|
||||||
|| oid != OID_sm2) {
|
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -355,16 +345,7 @@ int sm2_public_key_algor_from_der(const uint8_t **in, size_t *inlen)
|
|||||||
return 1;
|
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)
|
int sm2_private_key_info_to_der(const SM2_KEY *key, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
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;
|
const uint8_t *cp = buf;
|
||||||
size_t len;
|
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();
|
error_print();
|
||||||
return -1;
|
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;
|
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)
|
int sm2_public_key_info_to_der(const SM2_KEY *a, uint8_t **out, size_t *outlen)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(a, 0, sizeof(SM2_KEY));
|
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();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -532,7 +508,7 @@ int sm2_private_key_from_pem(SM2_KEY *a, FILE *fp)
|
|||||||
const uint8_t *cp = buf;
|
const uint8_t *cp = buf;
|
||||||
size_t len;
|
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();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -567,7 +543,7 @@ int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp)
|
|||||||
const uint8_t *cp = buf;
|
const uint8_t *cp = buf;
|
||||||
size_t len;
|
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();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -578,6 +554,10 @@ int sm2_public_key_info_from_pem(SM2_KEY *a, FILE *fp)
|
|||||||
return 1;
|
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])
|
int sm2_public_key_digest(const SM2_KEY *sm2_key, uint8_t dgst[32])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *der, s
|
|||||||
//FIXME: 由于每次加密的时候密文编码长度不同,因此这个函数应该避免在out == NULL时输出一个长度!
|
//FIXME: 由于每次加密的时候密文编码长度不同,因此这个函数应该避免在out == NULL时输出一个长度!
|
||||||
int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
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];
|
size_t cbuf[clen];
|
||||||
SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)cbuf;
|
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);
|
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[] = {
|
uint8_t zin[] = {
|
||||||
0x00, 0x80,
|
0x00, 0x80,
|
||||||
@@ -190,15 +190,13 @@ int sm2_compute_z(uint8_t z[32], const SM2_POINT *pub, const char *id)
|
|||||||
} else {
|
} else {
|
||||||
SM3_CTX ctx;
|
SM3_CTX ctx;
|
||||||
uint8_t idbits[2];
|
uint8_t idbits[2];
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = strlen(id);
|
idbits[0] = (uint8_t)(idlen >> 5);
|
||||||
idbits[0] = (uint8_t)(len >> 5);
|
idbits[1] = (uint8_t)(idlen << 3);
|
||||||
idbits[1] = (uint8_t)(len << 3);
|
|
||||||
|
|
||||||
sm3_init(&ctx);
|
sm3_init(&ctx);
|
||||||
sm3_update(&ctx, idbits, 2);
|
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, zin + 18, 128);
|
||||||
sm3_update(&ctx, pub->x, 32);
|
sm3_update(&ctx, pub->x, 32);
|
||||||
sm3_update(&ctx, pub->y, 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;
|
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];
|
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;
|
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_init(&ctx->sm3_ctx);
|
||||||
sm3_update(&ctx->sm3_ctx, z, 32);
|
sm3_update(&ctx->sm3_ctx, z, 32);
|
||||||
@@ -241,13 +239,13 @@ int sm2_sign_resume(SM2_SIGN_CTX *ctx)
|
|||||||
return 0;
|
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];
|
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;
|
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_init(&ctx->sm3_ctx);
|
||||||
sm3_update(&ctx->sm3_ctx, z, 32);
|
sm3_update(&ctx->sm3_ctx, z, 32);
|
||||||
memcpy(&ctx->key, key, sizeof(SM2_KEY));
|
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;
|
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);
|
memcpy(&key->private_key, private_key, 32);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: 检查公钥是否正确
|
int sm2_key_set_public_key(SM2_KEY *key, const SM2_POINT *public_key)
|
||||||
int sm2_set_public_key(SM2_KEY *key, const uint8_t public_key[64])
|
|
||||||
{
|
{
|
||||||
memcpy(&key->public_key, public_key, 64);
|
key->public_key = *public_key;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,67 +51,57 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <gmssl/sm2.h>
|
#include <gmssl/sm2.h>
|
||||||
|
#include <gmssl/asn1.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
// FIXME: 缺乏打印公钥的函数,有时候SM2_KEY中只有公钥,没有私钥
|
// 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");
|
format_print(fp, format, indent, "SM2PrivateKey\n");
|
||||||
indent += 4;
|
indent += 4;
|
||||||
format_bytes(fp, format, indent, "private_key : ", key->private_key, 32);
|
format_bytes(fp, format, indent, "private_key : ", key->private_key, 32);
|
||||||
format_print(fp, format, indent, "public_key:\n");
|
sm2_point_print(fp, format, indent + 4, "public_key", &key->public_key);
|
||||||
sm2_point_print(fp, &key->public_key, format, indent + 4);
|
|
||||||
return 1;
|
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, "x : ", P->x, 32);
|
||||||
format_bytes(fp, format, indent, "y : ", P->y, 32);
|
format_bytes(fp, format, indent, "y : ", P->y, 32);
|
||||||
return 1;
|
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 *sig = (SM2_SIGNATURE *)buf;
|
if (sm2_signature_from_der(&sig, &a, &alen) != 1
|
||||||
const uint8_t *p = der;
|
|| asn1_length_is_zero(alen) != 1) {
|
||||||
int i;
|
error_print();
|
||||||
|
return -1;
|
||||||
if (sm2_signature_from_der(sig, &p, &derlen) < 0) {
|
|
||||||
fprintf(stderr, "error: %s %d: invalid signature DER encoding\n", __FILE__, __LINE__);
|
|
||||||
}
|
}
|
||||||
if (derlen > 0) {
|
format_print(fp, fmt, ind, "%s\n", label);
|
||||||
fprintf(stderr, "error: %s %d: %zu extra bytes at the end of DER\n", __FILE__, __LINE__, derlen);
|
ind += 4;
|
||||||
}
|
format_bytes(fp, fmt, ind, "r : ", sig.r, 32);
|
||||||
|
format_bytes(fp, fmt, ind, "s : ", sig.s, 32);
|
||||||
format_bytes(fp, format, indent, "r : ", sig->r, 32);
|
|
||||||
format_bytes(fp, format, indent, "s : ", sig->s, 32);
|
|
||||||
return 1;
|
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;
|
SM2_CIPHERTEXT *c = (SM2_CIPHERTEXT *)buf;
|
||||||
const uint8_t *p = der;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (sm2_ciphertext_from_der(c, &p, &derlen) < 0) {
|
if (sm2_ciphertext_from_der(c, &a, &alen) != 1
|
||||||
fprintf(stderr, "error: %s %d: invalid ciphertext DER encoding\n", __FILE__, __LINE__);
|
|| asn1_length_is_zero(alen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (derlen > 0) {
|
format_print(fp, fmt, ind, "%s\n", label);
|
||||||
fprintf(stderr, "error: %s %d: %zu extra bytes at the end of DER\n", __FILE__, __LINE__, derlen);
|
ind += 4;
|
||||||
}
|
format_bytes(fp, fmt, ind, "XCoordinate", c->point.x, 32);
|
||||||
sm2_ciphertext_print(fp, c, format, indent);
|
format_bytes(fp, fmt, ind, "YCoordinate", c->point.y, 32);
|
||||||
return 1;
|
format_bytes(fp, fmt, ind, "HASH", c->hash, 32);
|
||||||
}
|
format_bytes(fp, fmt, ind, "CipherText", c->ciphertext, c->ciphertext_size);
|
||||||
|
|
||||||
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);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
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,
|
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;
|
const uint8_t *pin = in;
|
||||||
uint8_t *pout = out;
|
uint8_t *pout = out;
|
||||||
|
|||||||
@@ -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])
|
static int bn_from_hex(bn_t r, const char hex[65])
|
||||||
{
|
{
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
if (hex2bin(hex, 64, buf) < 0) {
|
size_t len;
|
||||||
|
if (hex_to_bytes(hex, 64, buf, &len) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bn_from_bytes(r, buf);
|
bn_from_bytes(r, buf);
|
||||||
|
|||||||
@@ -47,11 +47,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <gmssl/version.h>
|
||||||
#include <gmssl/md5.h>
|
|
||||||
#include "endian.h"
|
int gmssl_version_num(void)
|
||||||
|
{
|
||||||
|
return GMSSL_VERSION_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
const char *gmssl_version(void)
|
const char *gmssl_version(void)
|
||||||
{
|
{
|
||||||
return "GmSSL 3.0 alpha";
|
return GMSSL_VERSION_STR;
|
||||||
}
|
}
|
||||||
|
|||||||
634
src/x509_alg.c
Normal file
634
src/x509_alg.c
Normal file
@@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gmssl/oid.h>
|
||||||
|
#include <gmssl/asn1.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
508
src/x509_algor.c
508
src/x509_algor.c
@@ -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 <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <gmssl/oid.h>
|
|
||||||
#include <gmssl/asn1.h>
|
|
||||||
#include <gmssl/error.h>
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
1424
src/x509_asn1.c
1424
src/x509_asn1.c
File diff suppressed because it is too large
Load Diff
1229
src/x509_cer.c
Normal file
1229
src/x509_cer.c
Normal file
File diff suppressed because it is too large
Load Diff
808
src/x509_crl.c
808
src/x509_crl.c
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
|
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -49,415 +49,535 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <gmssl/crl.h>
|
#include <gmssl/asn1.h>
|
||||||
|
#include <gmssl/oid.h>
|
||||||
|
#include <gmssl/x509.h>
|
||||||
|
#include <gmssl/x509_crl.h>
|
||||||
|
#include <gmssl/x509_alg.h>
|
||||||
|
#include <gmssl/x509_ext.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
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) {
|
if (reason < 0 || reason >= x509_crl_reason_names_count) {
|
||||||
case X509_cr_unspecified: return "unspecified";
|
error_print();
|
||||||
case X509_cr_key_compromise: return "keyCompromise";
|
return NULL;
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return x509_crl_reason_names[reason];
|
||||||
}
|
}
|
||||||
|
|
||||||
84 typedef struct {
|
int x509_crl_reason_from_name(int *reason, const char *name)
|
||||||
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 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;
|
size_t len = 0;
|
||||||
if (asn1_integer_to_der(a->serial_number, a->serial_number_len, NULL, &len) != 1
|
if (!(info = asn1_oid_info_from_oid(x509_crl_entry_exts, x509_crl_entry_exts_count, oid))) {
|
||||||
|| x509_time_to_der(a->revoke_date, NULL, &len) != 1
|
error_print();
|
||||||
|| x509_extension_to_der(a->exts, NULL, &len) != 1
|
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_sequence_header_to_der(len, out, outlen) != 1
|
||||||
|| asn1_integer_to_der(a->serial_number, a->serial_number_len, out, outlen) != 1
|
|| asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) {
|
||||||
|| x509_time_to_der(a->revoke_date, out, outlen) != 1
|
|
||||||
|| x509_extension_to_der(a->exts, out, outlen) != 1) {
|
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
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;
|
int ret;
|
||||||
const uint8_t *data;
|
const uint8_t *p;
|
||||||
size_t datalen;
|
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();
|
if (ret < 0) error_print();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (asn1_integer_from_der(a->serial_number, &a->serial_number_len, &data, &datalen) != 1
|
if (asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1
|
||||||
|| x509_time_from_der(&a->revoke_date, &data, &datalen) != 1
|
|| asn1_generalized_time_from_der(revoke_date, &d, &dlen) != 1
|
||||||
|| x509_extensions_from_der(&a->exts, &data, &datalen) != 1
|
|| asn1_sequence_from_der(entry_exts, entry_exts_len, &d, &dlen) < 0
|
||||||
|| datalen) {
|
|| asn1_length_is_zero(dlen) != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int crl_revoked_cert_print(FILE *fp, const CRL_REVOKED_CERT *a, int format, int indent)
|
int x509_revoked_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
|
||||||
{
|
|
||||||
|
|
||||||
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 ret;
|
int ret;
|
||||||
const uint8_t *data;
|
const uint8_t *p;
|
||||||
size_t datalen;
|
size_t len;
|
||||||
|
time_t tv;
|
||||||
|
|
||||||
if ((ret = asn1_sequence_from_der(&data, &datalen, in, inlen)) != 1) {
|
if (asn1_integer_from_der(&p, &len, &d, &dlen) != 1) goto err;
|
||||||
if (ret < 0) error_print();
|
format_bytes(fp, fmt, ind, "userCertificate", p, len);
|
||||||
return ret;
|
if (asn1_generalized_time_from_der(&tv, &d, &dlen) != 1) goto err;
|
||||||
}
|
format_print(fp, fmt, ind, "revocationDate: %s\n", ctime(&tv));
|
||||||
if (asn1_int_from_der(&a->version, &data, &datalen) != 1
|
if ((ret = asn1_sequence_from_der(&p, &len, &d, &dlen)) < 0) goto err;
|
||||||
|| x509_algorithm_id_from_der(&a->signature_algor, &data, &datalen) != 1
|
//if (ret) x509_crl_entry_exts_print(fp, fmt, ind, "crlEntryExtensions", p, len); // 这里需要一个函数能够处理
|
||||||
|| x509_name_from_der(&a->issuer, &data, &datalen) != 1
|
if (asn1_length_is_zero(dlen) != 1) goto err;
|
||||||
|| 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);
|
|
||||||
return 1;
|
return 1;
|
||||||
|
err:
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const int X509_CRLExtensionOIDs[7] = {
|
static uint32_t oid_ce_authority_key_identifier[] = { oid_ce,35 };
|
||||||
OID_id_ce_authorityKeyIdentifier,
|
static uint32_t oid_ce_issuer_alt_name[] = { oid_ce,18 };
|
||||||
OID_id_ce_issuerAltName,
|
static uint32_t oid_ce_crl_number[] = { oid_ce,20 };
|
||||||
OID_id_ce_cRLNumber,
|
static uint32_t oid_ce_delta_crl_indicator[] = { oid_ce,27 };
|
||||||
OID_id_ce_deltaCRLIndicator,
|
static uint32_t oid_ce_issuing_distribution_point[] = { oid_ce,28 };
|
||||||
OID_id_ce_issuingDistributionPoint,
|
|
||||||
OID_id_ce_freshestCRL,
|
static const ASN1_OID_INFO x509_crl_exts[] = {
|
||||||
OID_pe_authorityInfoAccess,
|
{ 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]);
|
||||||
|
|
||||||
|
const char *x509_crl_ext_id_name(int oid)
|
||||||
void X509_CRLExtensionValue_to_der(const X509_CRLExtensionValue *a, int type, uint8_t **out, size_t *outlen)
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
const ASN1_OID_INFO *info;
|
||||||
case OID_id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier_to_der(&a->u.authorityKeyIdentifier, out, outlen); break;
|
if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid))) {
|
||||||
case OID_id_ce_issuerAltName: X509_GeneralNames_to_der(&a->u.issuerAltName, out, outlen); break;
|
error_print();
|
||||||
case OID_id_ce_cRLNumber: ASN1_INTEGER_to_der(&a->u.cRLNumber, out, outlen); break;
|
return NULL;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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) {
|
const ASN1_OID_INFO *info;
|
||||||
case OID_id_ce_authorityKeyIdentifier: return AuthorityKeyIdentifier_from_der(&a->u.authorityKeyIdentifier, in, inlen);
|
if (!(info = asn1_oid_info_from_name(x509_crl_exts, x509_crl_exts_count, name))) {
|
||||||
case OID_id_ce_issuerAltName: return X509_GeneralNames_from_der(&a->u.issuerAltName, in, inlen);
|
error_print();
|
||||||
case OID_id_ce_cRLNumber: return ASN1_INTEGER_from_der(&a->u.cRLNumber, in, inlen);
|
return OID_undef;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
return info->oid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int x509_crl_ext_id_to_der(int oid, uint8_t **out, size_t *outlen)
|
||||||
|
|
||||||
void X509_CRLExtension_to_der(const X509_CRLExtension *a, uint8_t **out, size_t *outlen)
|
|
||||||
{
|
{
|
||||||
ASN1_SEQUENCE_tag_length_to_der((ASN1_SEQUENCE *)a, out, outlen);
|
const ASN1_OID_INFO *info;
|
||||||
ASN1_OBJECT_IDENTIFIER_to_der(&a->extnID, out, outlen);
|
size_t len = 0;
|
||||||
ASN1_BOOLEAN_to_der(&a->critical, out, outlen);
|
if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid))) {
|
||||||
ASN1_OCTET_STRING_tag_length_to_der(&a->extnValue, out, outlen);
|
error_print();
|
||||||
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) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
data = a->extnValue.data;
|
if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1
|
||||||
length = a->extnValue.length;
|
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||||
if (X509_CRLExtensionValue_from_der(&a->extnValue_data, &data, &length) < 0
|
|| asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) {
|
||||||
|| length > 0) {
|
error_print();
|
||||||
return -1;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int x509_crl_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen)
|
||||||
|
|
||||||
|
|
||||||
// 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 ret;
|
int ret;
|
||||||
const uint8_t *data;
|
const uint8_t *p;
|
||||||
size_t length;
|
size_t len;
|
||||||
|
const ASN1_OID_INFO *info;
|
||||||
|
|
||||||
if ((ret = ASN1_SEQUENCE_from_der((ASN1_SEQUENCE *)a, in, inlen)) <= 0) {
|
*oid = 0;
|
||||||
return ret;
|
if ((ret = asn1_oid_info_from_der(&info, x509_crl_exts, x509_crl_exts_count, in, inlen)) != 1) {
|
||||||
}
|
error_print();
|
||||||
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) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
data = a->extnValue.data;
|
*oid = info->oid;
|
||||||
length = a->extnValue.length;
|
return ret;
|
||||||
if (X509_CRLEntryExtensionValue_from_der(&a->extnValue_data, &data, &length) < 0
|
}
|
||||||
|| length > 0) {
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
3302
src/x509_ext.c
3302
src/x509_ext.c
File diff suppressed because it is too large
Load Diff
240
src/x509_lib.c
240
src/x509_lib.c
@@ -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 <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <gmssl/sm2.h>
|
|
||||||
#include <gmssl/oid.h>
|
|
||||||
#include <gmssl/asn1.h>
|
|
||||||
#include <gmssl/x509.h>
|
|
||||||
#include <gmssl/error.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
444
src/x509_oid.c
Normal file
444
src/x509_oid.c
Normal file
@@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <gmssl/sm2.h>
|
||||||
|
#include <gmssl/oid.h>
|
||||||
|
#include <gmssl/asn1.h>
|
||||||
|
#include <gmssl/x509.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
511
src/x509_prn.c
Normal file
511
src/x509_prn.c
Normal file
@@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <gmssl/sm2.h>
|
||||||
|
#include <gmssl/oid.h>
|
||||||
|
#include <gmssl/asn1.h>
|
||||||
|
#include <gmssl/x509.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
383
src/x509_req.c
Normal file
383
src/x509_req.c
Normal file
@@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <gmssl/sm2.h>
|
||||||
|
#include <gmssl/oid.h>
|
||||||
|
#include <gmssl/asn1.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
#include <gmssl/x509.h>
|
||||||
|
#include <gmssl/pem.h>
|
||||||
|
#include <gmssl/x509_req.h>
|
||||||
|
#include <gmssl/x509_ext.h>
|
||||||
|
#include <gmssl/x509_alg.h>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
272
src/x509_str.c
Normal file
272
src/x509_str.c
Normal file
@@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <gmssl/sm2.h>
|
||||||
|
#include <gmssl/oid.h>
|
||||||
|
#include <gmssl/pem.h>
|
||||||
|
#include <gmssl/asn1.h>
|
||||||
|
#include <gmssl/x509_str.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -182,7 +182,7 @@ static const uint8_t S1[256] = {
|
|||||||
(X0 ^ R1) + R2; \
|
(X0 ^ R1) + R2; \
|
||||||
F_(X1, X2)
|
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;
|
ZUC_UINT31 *LFSR = key->LFSR;
|
||||||
uint32_t R1, R2;
|
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;
|
key->R2 = R2;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t zuc_generate_keyword(ZUC_KEY *key)
|
uint32_t zuc_generate_keyword(ZUC_STATE *key)
|
||||||
{
|
{
|
||||||
ZUC_UINT31 *LFSR = key->LFSR;
|
ZUC_UINT31 *LFSR = key->LFSR;
|
||||||
uint32_t R1 = key->R1;
|
uint32_t R1 = key->R1;
|
||||||
@@ -230,7 +230,7 @@ uint32_t zuc_generate_keyword(ZUC_KEY *key)
|
|||||||
return Z;
|
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;
|
ZUC_UINT31 *LFSR = key->LFSR;
|
||||||
uint32_t R1 = key->R1;
|
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;
|
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));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
zuc_set_key((ZUC_KEY *)ctx, key, iv);
|
zuc_init((ZUC_STATE *)ctx, key, iv);
|
||||||
ctx->K0 = zuc_generate_keyword((ZUC_KEY *)ctx);
|
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 T = ctx->T;
|
||||||
ZUC_UINT32 K0 = ctx->K0;
|
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;
|
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 T = ctx->T;
|
||||||
ZUC_UINT32 K0 = ctx->K0;
|
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] = {
|
static const ZUC_UINT7 ZUC256_D[][16] = {
|
||||||
{0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
|
{0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
@@ -413,8 +413,8 @@ static const ZUC_UINT7 ZUC256_D[][16] = {
|
|||||||
(uint32_t)(d))
|
(uint32_t)(d))
|
||||||
|
|
||||||
|
|
||||||
static void zuc256_set_mac_key(ZUC_KEY *key, const unsigned char K[32],
|
static void zuc256_set_mac_key(ZUC_STATE *key, const uint8_t K[32],
|
||||||
const unsigned char IV[23], int macbits)
|
const uint8_t IV[23], int macbits)
|
||||||
{
|
{
|
||||||
ZUC_UINT31 *LFSR = key->LFSR;
|
ZUC_UINT31 *LFSR = key->LFSR;
|
||||||
uint32_t R1, R2;
|
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;
|
key->R2 = R2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zuc256_set_key(ZUC_KEY *key, const unsigned char K[32],
|
void zuc256_init(ZUC_STATE *key, const uint8_t K[32],
|
||||||
const unsigned char IV[23])
|
const uint8_t IV[23])
|
||||||
{
|
{
|
||||||
zuc256_set_mac_key(key, K, IV, 0);
|
zuc256_set_mac_key(key, K, IV, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const unsigned char key[32],
|
void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const uint8_t key[32],
|
||||||
const unsigned char iv[23], int macbits)
|
const uint8_t iv[23], int macbits)
|
||||||
{
|
{
|
||||||
if (macbits < 32)
|
if (macbits < 32)
|
||||||
macbits = 32;
|
macbits = 32;
|
||||||
else if (macbits > 64)
|
else if (macbits > 64)
|
||||||
macbits = 128;
|
macbits = 128;
|
||||||
memset(ctx, 0, sizeof(*ctx));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
zuc256_set_mac_key((ZUC256_KEY *)ctx, key, iv, macbits);
|
zuc256_set_mac_key((ZUC256_STATE *)ctx, key, iv, macbits);
|
||||||
zuc256_generate_keystream((ZUC256_KEY *)ctx, macbits/32, ctx->T);
|
zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->T);
|
||||||
zuc256_generate_keystream((ZUC256_KEY *)ctx, macbits/32, ctx->K0);
|
zuc256_generate_keystream((ZUC256_STATE *)ctx, macbits/32, ctx->K0);
|
||||||
ctx->macbits = (macbits/32) * 32;
|
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;
|
ZUC_UINT32 K1, M;
|
||||||
size_t n = ctx->macbits / 32;
|
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);
|
M = GETU32(ctx->buf);
|
||||||
ctx->buflen = 0;
|
ctx->buflen = 0;
|
||||||
|
|
||||||
K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx);
|
K1 = zuc256_generate_keyword((ZUC256_STATE *)ctx);
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
if (M & 0x80000000) {
|
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) {
|
while (len >= 4) {
|
||||||
M = GETU32(data);
|
M = GETU32(data);
|
||||||
K1 = zuc256_generate_keyword((ZUC256_KEY *)ctx);
|
K1 = zuc256_generate_keyword((ZUC256_STATE *)ctx);
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
if (M & 0x80000000) {
|
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;
|
ZUC_UINT32 K1, M;
|
||||||
size_t n = ctx->macbits/32;
|
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) {
|
if (ctx->buflen || nbits) {
|
||||||
M = GETU32(ctx->buf);
|
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++) {
|
for (i = 0; i < ctx->buflen * 8 + nbits; i++) {
|
||||||
|
|||||||
@@ -50,23 +50,23 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <gmssl/zuc.h>
|
#include <gmssl/zuc.h>
|
||||||
|
|
||||||
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)
|
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[0] = iv[8] = count >> 24;
|
||||||
iv[1] = iv[9] = count >> 16;
|
iv[1] = iv[9] = count >> 16;
|
||||||
iv[2] = iv[10] = count >> 8;
|
iv[2] = iv[10] = count >> 8;
|
||||||
iv[3] = iv[11] = count;
|
iv[3] = iv[11] = count;
|
||||||
iv[4] = iv[12] = ((bearer << 1) | (direction & 1)) << 2;
|
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,
|
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_BIT direction)
|
||||||
{
|
{
|
||||||
ZUC_KEY zuc_key;
|
ZUC_STATE zuc_key;
|
||||||
size_t nwords = (nbits + 31)/32;
|
size_t nwords = (nbits + 31)/32;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
#include <gmssl/zuc.h>
|
#include <gmssl/zuc.h>
|
||||||
#include "endian.h"
|
#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)
|
ZUC_BIT direction)
|
||||||
{
|
{
|
||||||
memset(iv, 0, 16);
|
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
|
#if 1
|
||||||
ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits,
|
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_BIT direction)
|
||||||
{
|
{
|
||||||
ZUC_MAC_CTX ctx;
|
ZUC_MAC_CTX ctx;
|
||||||
unsigned char iv[16];
|
uint8_t iv[16];
|
||||||
unsigned char mac[4];
|
uint8_t mac[4];
|
||||||
zuc_set_eia_iv(iv, count, bearer, direction);
|
zuc_set_eia_iv(iv, count, bearer, direction);
|
||||||
zuc_mac_init(&ctx, key, iv);
|
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);
|
return GETU32(mac);
|
||||||
}
|
}
|
||||||
#else
|
#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 *)(p) + (i)/32)) & (1 << (31 - ((i) % 32)))) ? 1 : 0)
|
||||||
|
|
||||||
ZUC_UINT32 ZUC_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits,
|
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_BIT direction)
|
||||||
{
|
{
|
||||||
ZUC_UINT32 T = 0;
|
ZUC_UINT32 T = 0;
|
||||||
ZUC_KEY key;
|
ZUC_STATE key;
|
||||||
unsigned char iv[16];
|
uint8_t iv[16];
|
||||||
ZUC_UINT32 buf[ZUC_MAC_BUF_WORDS + 2];
|
ZUC_UINT32 buf[ZUC_MAC_BUF_WORDS + 2];
|
||||||
size_t nwords = (nbits + 31)/32;
|
size_t nwords = (nbits + 31)/32;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|||||||
Reference in New Issue
Block a user