On 06/08/2019 17:00, William Roberts wrote: > On Tue, Aug 6, 2019 at 10:56 AM Matt Caswell <matt@xxxxxxxxxxx> wrote: >> >> >> >> On 06/08/2019 16:34, William Roberts wrote: >>> Hi, >>> I occasionally get spurious errors in my ECDSA signatures, and it >>> appears that when the top byte is over 0x80 of either the R or S >>> component, that I get a zero pad. I noticed all this when reading >>> through the source, their was some comments (see below). I noticed a >>> d2i_ASN1_UINTEGER, but I can't find a coresponding i2d_ version to >>> create it. The zero pad seems to be the correct behavior, but it seems >>> to be breaking things. >> >> As you note the zero pad is the correct behaviour. >> >> >>> This is the link to the issue request I got filed for more details: >>> https://github.com/tpm2-software/tpm2-pkcs11/issues/277 >> >> This seems to be a problem in tmp2-pkcs11 and not OpenSSL. So its not clear to >> me what your question to openssl-users is? > > The questions is their is a d2i_ASN1_UINTEGER exists for that zero pad > issue, is their a i2d version, I couldn't find one. No, an i2d version does not exists. d2i_ASN1_UINTEGER exists only for interoperability with broken software. From the code (crypto/asn1/a_int.c): /* * This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1 * integers: some broken software can encode a positive INTEGER with its MSB * set as negative (it doesn't add a padding zero). */ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) Sine we don't want to *create* knowingly broken DER we don't provide the equivalent function. > > I guess a second question is, is their a better way to build an ECDSA > signature from the R and S components, the code > for ASNI sequence is something I never figured out, is their an > example in ossl somewhere? If you have the r and s components in raw "binary" format then something like this should create an OpenSSL ECDSA_SIG object (totally untested): ECDSA_SIG *create_ecdsa_sig(unsigned char *r, size_t rlen, unsigned char *s, size_t slen) { ECDSA_SIG *sig = ECDSA_SIG_new(); if (sig == NULL) return NULL; sig->r = BN_bin2bn(r, rlen, NULL); sig->s = BN_bin2bn(s, slen, NULL); if (sig->r == NULL || sig->s == NULL) { ECDSA_SIG_free(sig); return NULL; } return sig; } Once you have the ECDSA_SIG structure then encoding it as DER is simply a call to i2d_ECDSA_SIG: https://www.openssl.org/docs/manmaster/man3/i2d_ECDSA_SIG.html Matt