From 80c496671f5bb513a1298b462040ed12d549fb2b Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 15 Feb 2015 13:56:51 +0100 Subject: [PATCH] helper functions to change format of ECDSA signature --- src/libopensc/asn1.c | 79 ++++++++++++++++++++++++++++++++- src/libopensc/asn1.h | 11 ++++- src/libopensc/libopensc.exports | 2 + 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 189075ba..fb09a1f4 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -1002,7 +1002,7 @@ static const struct sc_asn1_entry c_asn1_se_info[4] = { }; static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen, - sc_pkcs15_sec_env_info_t ***se, size_t *num, int depth) + sc_pkcs15_sec_env_info_t ***se, size_t *num, int depth) { struct sc_pkcs15_sec_env_info **ses; const unsigned char *ptr = obj; @@ -1819,3 +1819,80 @@ sc_encode_oid (struct sc_context *ctx, struct sc_object_id *id, return SC_SUCCESS; } + +#define C_ASN1_SIG_VALUE_SIZE 2 +static struct sc_asn1_entry c_asn1_sig_value[C_ASN1_SIG_VALUE_SIZE] = { + { "ECDSA-Sig-Value", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + +#define C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE 3 +static struct sc_asn1_entry c_asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE] = { + { "r", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL }, + { "s", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + + +int +sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen) +{ + struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; + struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; + unsigned char *r = in, *s = in + inlen/2; + size_t r_len = inlen/2, s_len = inlen/2; + int rv; + + LOG_FUNC_CALLED(ctx); + sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value); + sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 1); + + sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients); + sc_format_asn1_entry(asn1_sig_value_coefficients + 0, r, &r_len, 1); + sc_format_asn1_entry(asn1_sig_value_coefficients + 1, s, &s_len, 1); + + rv = sc_asn1_encode(ctx, asn1_sig_value, buf, buflen); + LOG_TEST_RET(ctx, rv, "ASN.1 encoding ECDSA-SIg-Value failed"); + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); +} + + +int +sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen) +{ + struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; + struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; + unsigned char *r, *s; + size_t r_len, s_len; + int rv; + + LOG_FUNC_CALLED(ctx); + sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value); + sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 0); + + sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients); + sc_format_asn1_entry(asn1_sig_value_coefficients + 0, &r, &r_len, 0); + sc_format_asn1_entry(asn1_sig_value_coefficients + 1, &s, &s_len, 0); + + rv = sc_asn1_decode(ctx, asn1_sig_value, in, inlen, NULL, NULL); + LOG_TEST_RET(ctx, rv, "ASN.1 decoding ECDSA-Sig-Value failed"); + + sc_log(ctx, "r(%i): %s", r_len, sc_dump_hex(r, r_len)); + sc_log(ctx, "s(%i): %s", s_len, sc_dump_hex(s, s_len)); + + *buf = malloc(r_len + s_len); + if (*buf == NULL) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + + memcpy(*buf, r, r_len); + memcpy(*buf + r_len, s, s_len); + *buflen = r_len + s_len; + + free(r); + free(s); + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); +} diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index ef674d03..13958845 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -58,7 +58,7 @@ void sc_format_asn1_entry(struct sc_asn1_entry *entry, void *parm, void *arg, int set_present); void sc_copy_asn1_entry(const struct sc_asn1_entry *src, struct sc_asn1_entry *dest); - + /* DER tag and length parsing */ int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1, const u8 *in, size_t len, const u8 **newp, size_t *left); @@ -103,7 +103,7 @@ int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen, int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out); int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen, struct sc_object_id *id); -int sc_asn1_encode_object_id(u8 **buf, size_t *buflen, +int sc_asn1_encode_object_id(u8 **buf, size_t *buflen, const struct sc_object_id *id); /* algorithm encoding/decoding */ @@ -120,6 +120,13 @@ void sc_asn1_clear_algorithm_id(struct sc_algorithm_id *); int sc_asn1_write_element(sc_context_t *ctx, unsigned int tag, const u8 * data, size_t datalen, u8 ** out, size_t * outlen); +int sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, + unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen); +int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, + unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen); + #define SC_ASN1_CLASS_MASK 0x30000000 #define SC_ASN1_UNI 0x00000000 /* Universal */ #define SC_ASN1_APP 0x10000000 /* Application */ diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 0b98db2a..23f6c05a 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -51,6 +51,8 @@ sc_asn1_put_tag sc_asn1_skip_tag sc_asn1_verify_tag sc_asn1_write_element +sc_asn1_sig_value_sequence_to_rs +sc_asn1_sig_value_rs_to_sequence sc_base64_decode sc_base64_encode sc_bin_to_hex