1
$\begingroup$

I am trying to generate an ECDSA signature using ARM's CryptoCell 310 (hardware cryptography module) and verify the signature using mbedTLS software library.

The harware module documentation says that the ECDSA is performed according to ANS X9.62 standard.

The cryptocell generated signature for SECP256R1 is 64 bytes long and looks like this:

95D9AFCC53A8618FF99AA7AB86013F59148B112BDFB15A7775BDE04B1001A84AB77A0F1C82327BA3B420AA172DB288CA030028CAF7C43637EF3B9990B21D082C

I need to convert it into DER encoded signature so that mbedTLS can verify it, but I don't know how the R and S parameters are encoded in it. I have tried to take first half of that string as the R parameter, second half as S and encode it to DER like this:

304602210095D9AFCC53A8618FF99AA7AB86013F59148B112BDFB15A7775BDE04B1001A84A022100B77A0F1C82327BA3B420AA172DB288CA030028CAF7C43637EF3B9990B21D082C

Unfortunately it didn't work. I have also tried to do big/little endian swaps, trying the second half as R and first as S, but it still didn't work.

I have tried to obtain the X9.62 standard, but couldn't find anything about the encoding.

Does anyone know what encoding is that?

Thanks in advance.

$\endgroup$
4
$\begingroup$

ANS X9.62–2005 states in appendix E.8:

When a digital signature is represented with ASN.1, the digital signature shall be ASN.1 encoded using the following syntax:

ECDSA-Sig-Value ::= SEQUENCE {
    r INTEGER,
    s INTEGER
}

I found no issue with the DER encoding in the question.

Implementing this is a pain in the neck if there's no library for it (from a painful experience: a common language runtime once accepted invalid encoding with more zero bits in the high order bits of $r$ and $s$ than allowed by ASN.1, then became more strict, breaking invalid but working code calling it).

Update: the standard also states:

X.509 certificates and CRLs and CMS SignedData represent signatures as a bit string. Where a certificate, CRL or SignedData is signed with ECDSA, the entire encoding of a value of ASN.1 type ECDSA-Sig-Value shall be the value of the bit string.

But AFAIK this is only for certificates.

Now this looks like a purely programming issue, largely off-topic. Best option seems to be: dig documentation or test case for mbedTLS.

| improve this answer | |
$\endgroup$
1
$\begingroup$

This is an old and off-topic question, but having just struggled a day with the same problem, couldn't resist answering. ASN.1 bignum's are tricky, and using the raw bytes from the token doesn't work. Instead, the data from token, two 256-bit integers R and S need to be first read by mbedtls_mpi_read_binary after which the ASN.1 signature can be written by mbedtls_asn1_write_mpi. Like this (dsig_data is the data returned from C_Sign, mpi_size is 32)

    mbedtls_mpi R;
    mbedtls_mpi S;
    mbedtls_mpi_init(&R);
    mbedtls_mpi_init(&S);
    MBEDCERC(mbedtls_mpi_read_binary(&R, dsig_data, mpi_size));
    MBEDCERC(mbedtls_mpi_read_binary(&S, dsig_data + mpi_size, mpi_size));

    unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
    unsigned char *p = buf + sizeof buf;
    size_t len = 0;
    int ret = 0;

    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, &S));
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, &R));
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,
                                                     MBEDTLS_ASN1_CONSTRUCTED
                                                     | MBEDTLS_ASN1_SEQUENCE));
    mbedtls_mpi_free(&R);
    mbedtls_mpi_free(&S);
    memcpy(sig, p, len);
    *sig_len = len;
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.