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.
> >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:

    int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
                    unsigned int *len)
    {
        return(ASN1_item_digest(ASN1_ITEM_rptr(X509),type,(char *)data,md,len));
    }

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
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));

this should place the requisite digest in mdbuf.  Then ASN1_item_sign()
needs to deal with padding, etc., which is signature algorithm dependent.

> 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.

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;

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

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

Reply via email to