> From: owner-openssl-us...@openssl.org On Behalf Of Viktor Dukhovni
> Sent: Friday, 10 May, 2013 12:20

> On Fri, May 10, 2013 at 11:26:35AM -0400, Ken Goldman wrote:
> 
> > >a) get the der encoded value of tbsCertificate field
> > >b) hash it
> > >c) apply pkcs1 padding and sign it
> > >d) put the signature on asn1 form
> > >e) add NIDs and other parameters to the cert_info field 
> you identified.

The 'signature' (really X509_ALGOR aka AlgorithmIdentifier) 
*within* cert_info (which is tbsCertificate) must be set 
before 'a' is done. It contains one OID (typically but not 
necessarily derived from NID) and syntactically can contain 
parameters but I don't see why it ever would. (AlgId for a key 
does depending on alg, AlgId for using a key doesn't need to.)

After 'd' combine cert_info-aka-TBS + (copy of) AlgId + signature 
(in BITSTRING). (More below.)

> > >I spent a lot of time learning from forums and openssl code
> > >(X509_REQ_sign and functions it calls in my case) what I 
> need to do. If
> > >you can, go for option 1). If nto I may help you more later with 2)
> > 
> > Yes, your flow is the same as mine.  I'm looking for advice on the C
> > function calls.  Specifically,
> > 
> > Is X509_digest() useful for a) and b)?
> 
> No.  It is used to obtained digests of fully-formed certificates,
> including the existing signature, when signing a certificate,
> one signs only the parts that exclude the signature algorithm
> information and the signature bits.
> 
> If you look at X509_digest() it is a simple wrapper around 
> ASN1_item_digest: <snip>

Right. The hash of the complete cert is often used as a 
"fingerprint" for display to a human, as a (overwhelmingly) 
unique and quickly distinguishable identifier of a cert.

> If you look at X509_sign(), it wraps ASN1_item_sign():
> 
>     int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
>     {
>         x->cert_info->enc.modified = 1;
>         return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF),
>                             x->cert_info->signature, x->sig_alg,
>                             x->signature, x->cert_info,pkey,md));
>     }
> 
> The thing to notice is that ASN.1 representation structure in 
> the second
> case is for X509_CINF, not X509.  The former excludes the 
> signature part

and the data encoded (as X509_CINF) is x->cert_info.

> of the certificate.  So my guess for exctracting a signature 
> to be signed
> is that you want:
> 
>     X509 *cert;
>     EVP_MD *mdalg = EVP_get_digestbyname("sha1"); /* or whatever */
>     unsigned char mdbuf[EVP_MAX_MD_SIZE];
>     unsigned int mdlen;
> 
>     cert = ...;
>     ASN1_item_digest(ASN1_ITEM_rptr(X509_CINF), mdalg, cert, 
> mdbuf, &mdlen));
> 
Data should be cert->cert_info as above.

> this should place the requisite digest in mdbuf.  Then 
> ASN1_item_sign()
> needs to deal with padding, etc., which is signature 
> algorithm dependent.
> 
It lets EVP_DigestSign* deal with padding and signing algorithm. 
OP needs an equivalent using his HSM. 

> > Is there a high level call for d) and e) or must I do it using the
> > ASN.1 API?
> 
> An in memory X509 certificate is:
> 
>     struct x509_st {
>       X509_CINF *cert_info;
>       X509_ALGOR *sig_alg;
>       ASN1_BIT_STRING *signature;
>       ...
>     }
> 
> Just update the sig_alg and signature freeing old values and
> replacing with new and set x->cert_info->enc.modified = 1.
> 
If there are old values; it sounded to me like OP was constructing 
a new cert from scratch. In that case I think you also don't need 
enc.modified, but maybe better safe than sorry.

> The signature update code in ASN1_item_sign_ctx looks like:
> 
>       if (signature->data != NULL)
>           OPENSSL_free(signature->data);
>         signature->data = mdbuf;
>         signature->length = mdlen;
>         /* Make sure that the bit string has a 'not-used 
> bits' value of 0 */
>         signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
>         signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
> 
Almost, but you've mixed tabs and spaces in a way that makes 
the indentation misleading.

> So all you need to figure out is how to set the sig_alg...

As above all you really need is the OID; _item_sign_ctx shows 
how to do the parameter but in practice it's NULL or omitted.


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to