X509_REQ Handling -- SSLeay 0.9.0b -- January 1999

NAME

X509_REQ_new, X509_REQ_free, X509_REQ_dup, i2d_X509_REQ, d2i_X509_REQ,
d2i_X509_REQ_fp, i2d_X509_REQ_fp, d2i_X509_REQ_bio, i2d_X509_REQ_bio,
X509_REQ_print_fp, X509_REQ_print, PEM_write_bio_X509_REQ, PEM_write_X509_REQ,
PEM_read_bio_X509_REQ, PEM_read_X509_REQ, X509_REQ_verify, X509_REQ_sign,
X509_REQ_get_version, X509_REQ_get_subject_name, X509_REQ_set_version, X509_REQ_set_subject_name,
X509_REQ_extract_key, X509_REQ_get_pubkey, X509_REQ_set_pubkey, X509_to_X509_REQ,
X509_REQ_to_X509 -- X509_REQ Handling

SYNOPSIS

#include "x509.h"

X509_REQ *X509_REQ_new();

void X509_REQ_free(a)
X509_REQ *a;

X509_REQ *X509_REQ_dup(req)
X509_REQ *req;

int i2d_X509_REQ(a, pp)
X509_REQ *a;
unsigned char **pp;

X509_REQ *d2i_X509_REQ(a, pp, length)
X509_REQ **a;
unsigned char **pp;
long length;

X509_REQ *d2i_X509_REQ_fp(fp, req)
FILE *fp;
X509_REQ *req;

int i2d_X509_REQ_fp(fp, req)
FILE *fp;
X509_REQ *req;

X509_REQ *d2i_X509_REQ_bio(bp, req)
BIO *bp;
X509_REQ *req;

int i2d_X509_REQ_bio(bp, req)
BIO *bp;
X509_REQ *req;

int X509_REQ_print_fp(bp, req)
FILE *bp;
X509_REQ *req;

int X509_REQ_print(bp, req)
BIO *bp;
X509_REQ *req;

int X509_REQ_verify(a, r)
X509_REQ *a;
EVP_PKEY *r;

int X509_REQ_sign(x, pkey, md)
X509_REQ *x;
EVP_PKEY *pkey;
EVP_MD *md;

int X509_REQ_set_version(x, version)
X509_REQ *x;
long version;

int X509_REQ_set_subject_name(req, name)
X509_REQ *req;
X509_NAME *name;

EVP_PKEY * X509_REQ_get_pubkey(req)
X509_REQ *req;

int X509_REQ_set_pubkey(x, pkey)
X509_REQ *x;
EVP_PKEY *pkey;

X509_REQ *X509_to_X509_REQ(x, pkey, md)
X509 *x;
EVP_PKEY *pkey;
EVP_MD *md;

X509 *X509_REQ_to_X509(r, days, pkey)
X509_REQ *r;
int days;
EVP_PKEY *pkey;

DESCRIPTION

If you haven't read through the ASN.1 documentation, you probably had better do so; this library relies heavily on that code.

Here's the ASN.1 for a certificate request:

CertificationRequest ::= SEQUENCE {
  certificationRequestInfo        CertificationRequestInfo,
  signatureAlgorithm              SignatureAlgorithmIdentifier,
  signature                       Signature }

CertificationRequestInfo ::= SEQUENCE {
  version                         Version,
  subject                         Name,
  subjectPublicKeyInfo            SubjectPublicKeyInfo,
  attributes                      [0] IMPLICIT Attributes }

Now let's look at X509_REQ as the library defines it:

typedef struct X509_req_info_st
        {
        ASN1_INTEGER *version;
        X509_NAME *subject;
        X509_PUBKEY *pubkey;
        /*  d=2 hl=2 l=  0 cons: cont: 00 */
        STACK /* X509_ATTRIBUTE */ *attributes; /* [ 0 ] */
        int req_kludge;
        } X509_REQ_INFO;

typedef struct X509_req_st
        {
        X509_REQ_INFO *req_info;
        X509_ALGOR *sig_alg;
        ASN1_BIT_STRING *signature;
        int references;
        } X509_REQ;

Treating the certificate request as a more-or-less opaque type, we have the following operations we can perform on it:

make a new one, free an old one, copy it

X509_REQ_new, X509_REQ_free, X509_REQ_dup

convert it to/from DER-encoded form

i2d_X509_REQ, d2i_X509_REQ

write it to a file, or read it from a file, either in DER-encoded form or in human-readable text or in PEM (base64-encoded) form

d2i_X509_REQ_fp, i2d_X509_REQ_fp, d2i_X509_REQ_bio, i2d_X509_REQ_bio, X509_REQ_print_fp, X509_REQ_print, PEM_write_bio_X509_REQ, PEM_write_X509_REQ, PEM_read_bio_X509_REQ, PEM_read_X509_REQ

verify it, sign it

X509_REQ_verify, X509_REQ_sign

If we want to deal with the subfields of the structure instead, we can retrieve a pointer to any of them

X509_REQ_get_version, X509_REQ_get_subject_name

stuff any of them with a value or structure of our choice

X509_set_version, X509_set_subject_name

And finally there is a collection of routines that deal with the public or private key associated with the certificate on a more detailed level

X509_REQ_extract_key (=X509_REQ_get_pubkey), X509_REQ_get_pubkey, X509_REQ_set_pubkey

and a couple of routines that 'convert' from X509_REQ to X509 and vice versa

X509_to_X509_REQ, X509_REQ_to_X509

We'll look at each of these in turn.

X509_REQ_new creates a new X509_REQ structure and returns a pointer to it; if memory cannot be allocated it returns NULL.

X509_REQ_free frees the memory of the X509_REQ structure pointed to by a, unless the argument is NULL, in which case it does nothing.

X509_REQ_dup is actually a macro:

#define X509_REQ_dup(req) (X509_REQ *)ASN1_dup((int (*)())i2d_X509_REQ, 
                (char *(*)())d2i_X509_REQ,(char *)req)

It makes a copy of the X509_REQ structure that req points to and returns it, or NULL on error.

i2d_X509_REQ converts an X509_REQ structure pointed to by a to DER-encoded form; it places the results in *pp and then increments *pp to point to the end of the byte string it has just written, so you can call several i2d functions in a row. It returns the number of bytes written to the string or 0 on error.

See ASN.1 conversion to and from DER-encoded form for more on i2d functions.

d2i_X509_REQ converts length bytes of the DER-encoded string in *pp to an X509_REQ structure, updates *pp to point to the next byte to be processed, places the new X509_REQ structure in *a, and returns it, or NULL on error.

See ASN.1 conversion to and from DER-encoded form for more on d2i functions.

The following macros are provided for the convenience of the user:

#define d2i_X509_REQ_fp(fp,req)
  (X509_REQ *)ASN1_d2i_fp((char *(*)())X509_REQ_new, 
  (char *(*)())d2i_X509_REQ, (fp),(unsigned char **)(req))

#define i2d_X509_REQ_fp(fp,req)
 ASN1_i2d_fp(i2d_X509_REQ,fp,(unsigned char *)req)

#define d2i_X509_REQ_bio(bp,req)
 (X509_REQ *)ASN1_d2i_bio((char *(*)())X509_REQ_new, 
 (char *(*)())d2i_X509_REQ, (bp),(unsigned char **)(req))

#define i2d_X509_REQ_bio(bp,req)
  ASN1_i2d_bio(i2d_X509_REQ,bp,(unsigned char *)req)

d2i_X509_REQ_fp reads from fp as much data as it can, in DER-encoded form, and then uses d2i_X509_REQ to translate that into an X509_REQ structure, which is placed in req if that argument is not NULL, or into a newly malloced structure otherwise. A pointer to the populated structure is returned, or NULL on error.

i2d_X509_REQ_fp converts the X509_REQ structure pointed to by req to DER-encoded form and writes it out to the file pointer fp.

It returns 1 on success and 0 on error.

d2i_X509_REQ_bio does exactly what d2i_X509_REQ_fp does, except that it reads from a BIO instead of a file pointer.

i2d_X509_REQ_bio does exactly what i2d_X509_REQ_fp does, except that it writes to a BIO instead of a file pointer.

X509_REQ_print_fp translates the X509_REQ structure req into human-readable format and writes the result to the file pointer fp. It returns 1 on success or 0 on error.

It uses a fixed format to display the certificate request information. An example is below:

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=AU, ST=Queensland, L=Brisbane, O=CryptSoft Pty Ltd, CN=Eric Young/Email=eay@mincom.oz.au
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (512 bit)
                Modulus (512 bit):
                    00:eb:c6:20:44:34:59:0b:df:e3:5a:ee:82:3a:e6:
                    cf:59:28:a6:ed:2f:0f:0f:b0:83:c8:c7:dd:c4:b9:
                    8a:81:38:04:c9:1a:b5:ad:a4:17:3d:59:3f:36:67:
                    90:9f:4b:8e:68:1d:fa:3d:96:4d:63:f1:0e:fe:b5:
                    98:b5:56:35:3b
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: md5WithRSAEncryption
        12:e4:10:35:01:55:4e:88:07:af:19:22:a1:14:29:27:86:d1:
        a1:22:15:34:57:dc:e6:ed:26:99:52:54:3b:b0:68:bb:a8:b0:
        4a:2e:52:d9:16:59:9d:5d:d2:92:d3:8e:39:d9:4b:b7:4c:f6:
        4f:a4:8e:fb:be:39:d1:e7:29:89

X509_REQ_print does exactly the same thing as X509_REQ_print_fp, except that it writes to a BIO instead of a file pointer.

The following macros are provided for the convenience of the user:

#define PEM_write_X509_REQ(fp,x) 
  PEM_ASN1_write((int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,fp,(char *)x,
  NULL,NULL,0,NULL)

#define PEM_read_X509_REQ(fp,x,cb) 
  (X509_REQ *)PEM_ASN1_read((char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,
  fp,(char **)x,cb)

#define PEM_write_bio_X509_REQ(bp,x) 
  PEM_ASN1_write_bio((int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,bp,(char *)x,
  NULL,NULL,0,NULL)

#define PEM_read_bio_X509_REQ(bp,x,cb) 
  (X509_REQ *)PEM_ASN1_read_bio((char *(*)())d2i_X509_REQ,
  PEM_STRING_X509_REQ,bp,(char **)x,cb)

PEM_write_X509_REQ converts the X509_REQ structure pointed to by x to DER-encoded form. The data is then base64-encoded and written out to fp with BEGIN CERTIFICATE REQUEST and END headers around it. 1 is returned on success, or 0 on error.

PEM_write_bio_X509_REQ does the same thing as PEM_write_X509_REQ except that it uses a BIO instead of a FILE.

PEM_read_X509_REQ reads a PEM-encoded X509 certificate request from the file fp using PEM_read; calls PEM_get_EVP_CIPHER_INFO to process any DEK-Info header that might be present, in particular determining the cipher that was used to encrypt the message body and retrieving the ivec from the header; calls PEM_do_header to decrypt the message body if it was encrypted (see the description of that function in PEM library routines for details about how a pass phrase (key string) is retrieved from the user, using the callback cb, or retrieved from somewhere else); and then converts it to an X509_REQ structure and places the result in x.

It then returns a pointer to that structure, or NULL on error.

The file must contain a BEGIN CERTIFICATE REQUEST header or it will not be parsed properly.

Note that since this function calls PEM_get_EVP_CIPHER_INFO, the appropriate cipher type (according to the name that is present in the PEM header) must be loaded into the static cipher and possibly static alias stack in order for the function to succeed; EVP cipher/digest lookup routines for more on this. Ordinaily this will not be a problem, since the certificate request will not have been written out in encrypted form.

This function can be used to read a list of certificate requests from a file.

PEM_read_bio_X509_REQ does the same thing as PEM_X509_REQ_read but uses a BIO instead of a file pointer.

The following macros are provided for the convenience of the user:

#define X509_REQ_verify(a,r) 
  ASN1_verify((int (*)())i2d_X509_REQ_INFO,a->sig_alg,a->signature,(char *)a->req_info,r)

#define X509_REQ_sign(x,pkey,md) 
  ASN1_sign((int (*)())i2d_X509_REQ_INFO,x->sig_alg, NULL, x->signature, 
  (char *)x->req_info,pkey,md)

X509_REQ_verify converts the X509_REQ_INFO structure a->req_info to DER-encoded form; computes the message digest of it, using a->sig_alg as the message digest algorithm; signs it using r as the key for signing; and finally compares the results against a->signature. 1 is returned if they match, 0 on failure or error.

This function actually just calls ASN1_verify, which calls EVP_VerifyInit, EVP_VerifyUpdate, and EVP_VerifyFinal; see EVP digest handling, signing, verification if you want details on these functions.

NOTE: this routine calls the dreaded EVP_get_digestbyname() which means that the static digest and alias stacks must be initialized; see EVP cipher/digest lookup routines for more on this.

X509_REQ_sign sets both x->signature and x->sig_alg to hold the appropriate information for the algorithm md->pkey_type, which might be for example NID_shaWithRSAEncryption. Then it converts x->req_info to DER-encoded form, uses the digest algorithm specified by type to compute a message digest of the DER-encoded string and uses the pkey to sign it. The result is placed in x->signature->data with the length in x->signature->length. That same length is returned to the caller, or 0 on error.

This function actually just calls ASN1_sign, which calls EVP_SignInit, EVP_SignUpdate, and EVP_SignFinal; see EVP digest handling, signing, verification if you want details on these functions.

The following macros are provided for the convenience of the user:

#define     X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version)
#define     X509_REQ_get_subject_name(x) ((x)->req_info->subject)

X509_REQ_get_version translates the ASN1_INTEGER version subfield of the certificate request pointed to by x, to a long and returns it.

X509_REQ_get_subject_name returns a pointer to the subject subfield of the certificate request pointed to by a.

X509_REQ_set_version translates the long version to an ASN1_INTEGER and stuffs it into the version subfield of the certificate request pointed to by x. It returns 1 on success or 0 on error.

X509_REQ_set_subject_name copies the X509_NAME pointed to by name into the subject subfield of the certificate request pointed to by req. It returns 1 on success or 0 on error.

The following functions all manipulate keys associated with an X509 certificate. See X.509 Certificate Subfields Handling for more details on the functions they call.

The following macro is provided for the convenience of the user:

#define X509_REQ_extract_key(a)     X509_REQ_get_pubkey(a) 

X509_REQ_get_pubkey calls X509_PUBKEY_get on x->req_info->key to extract the public key from the certificate request and turn it into an EVP_PKEY which can be used for encryption with EVP routines. See Overview of EVP interfaces for a discussion of the EVP library.

The EVP_PKEY structure is cached in the X509_REQ_INFO structure for later use as well. If this function is called again, a pointer to the cached copy is used rather than doing the conversion again.

It returns a pointer to the EVP_PKEY or NULL on error.

X509_REQ_set_pubkey calls X509_PUBKEY_set to convert the EVP_PKEY structure pointed to by pkey to DER-encoded form and stuff it and its various subfields into x->req_info->key as appropriate. It returns 1 on success and 0 on error.

X509_to_X509_REQ creates a new certificate request with subject name the same as in the certificate, version 0, pubkey from the certificate, and signing the request with pkey as the key and md as the digest. It returns a pointer to the new request or NULL on error. This function does not handle extensions at all. This function is called in apps/ca and apps/x509.

X509_REQ_to_X509 creates an X509 certificate with subject and issuer the same as the subject in the request r, with validity days, and pkey used to sign it (with md5 as the digest). It returns a pointer to the new certificate if all goes well, or NULL on error. It duplicates the X509_REQ_INFO subfield of the certificate request and never frees it; this is a memory leak I suppose. The duplication is pretty slow, too, since it does i2d_X509_REQ_INFO and then d2i_X509_REQ_INFO. Also, this function does not handle extensions in the request properly. In fact I don't know why anyone would call this routine. In fact, nothing *does* call this routine.