155714Skris/* crypto/x509/x509_req.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280304Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280304Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280304Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280304Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280304Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/bn.h>
6255714Skris#include <openssl/evp.h>
6355714Skris#include <openssl/asn1.h>
64238405Sjkim#include <openssl/asn1t.h>
6555714Skris#include <openssl/x509.h>
6655714Skris#include <openssl/objects.h>
6755714Skris#include <openssl/buffer.h>
6855714Skris#include <openssl/pem.h>
6955714Skris
7059191SkrisX509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
71280304Sjkim{
72280304Sjkim    X509_REQ *ret;
73280304Sjkim    X509_REQ_INFO *ri;
74280304Sjkim    int i;
75280304Sjkim    EVP_PKEY *pktmp;
7655714Skris
77280304Sjkim    ret = X509_REQ_new();
78280304Sjkim    if (ret == NULL) {
79280304Sjkim        X509err(X509_F_X509_TO_X509_REQ, ERR_R_MALLOC_FAILURE);
80280304Sjkim        goto err;
81280304Sjkim    }
8255714Skris
83280304Sjkim    ri = ret->req_info;
8455714Skris
85280304Sjkim    ri->version->length = 1;
86280304Sjkim    ri->version->data = (unsigned char *)OPENSSL_malloc(1);
87280304Sjkim    if (ri->version->data == NULL)
88280304Sjkim        goto err;
89280304Sjkim    ri->version->data[0] = 0;   /* version == 0 */
9055714Skris
91280304Sjkim    if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x)))
92280304Sjkim        goto err;
9355714Skris
94280304Sjkim    pktmp = X509_get_pubkey(x);
95280304Sjkim    if (pktmp == NULL)
96280304Sjkim        goto err;
97280304Sjkim    i = X509_REQ_set_pubkey(ret, pktmp);
98280304Sjkim    EVP_PKEY_free(pktmp);
99280304Sjkim    if (!i)
100280304Sjkim        goto err;
10155714Skris
102280304Sjkim    if (pkey != NULL) {
103280304Sjkim        if (!X509_REQ_sign(ret, pkey, md))
104280304Sjkim            goto err;
105280304Sjkim    }
106280304Sjkim    return (ret);
107280304Sjkim err:
108280304Sjkim    X509_REQ_free(ret);
109280304Sjkim    return (NULL);
110280304Sjkim}
11155714Skris
11255714SkrisEVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
113280304Sjkim{
114280304Sjkim    if ((req == NULL) || (req->req_info == NULL))
115280304Sjkim        return (NULL);
116280304Sjkim    return (X509_PUBKEY_get(req->req_info->pubkey));
117280304Sjkim}
11855714Skris
119160814Ssimonint X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
120280304Sjkim{
121280304Sjkim    EVP_PKEY *xk = NULL;
122280304Sjkim    int ok = 0;
123160814Ssimon
124280304Sjkim    xk = X509_REQ_get_pubkey(x);
125280304Sjkim    switch (EVP_PKEY_cmp(xk, k)) {
126280304Sjkim    case 1:
127280304Sjkim        ok = 1;
128280304Sjkim        break;
129280304Sjkim    case 0:
130280304Sjkim        X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
131280304Sjkim                X509_R_KEY_VALUES_MISMATCH);
132280304Sjkim        break;
133280304Sjkim    case -1:
134280304Sjkim        X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH);
135280304Sjkim        break;
136280304Sjkim    case -2:
137160814Ssimon#ifndef OPENSSL_NO_EC
138280304Sjkim        if (k->type == EVP_PKEY_EC) {
139280304Sjkim            X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
140280304Sjkim            break;
141280304Sjkim        }
142160814Ssimon#endif
143160814Ssimon#ifndef OPENSSL_NO_DH
144280304Sjkim        if (k->type == EVP_PKEY_DH) {
145280304Sjkim            /* No idea */
146280304Sjkim            X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
147280304Sjkim                    X509_R_CANT_CHECK_DH_KEY);
148280304Sjkim            break;
149280304Sjkim        }
150160814Ssimon#endif
151280304Sjkim        X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE);
152280304Sjkim    }
153160814Ssimon
154280304Sjkim    EVP_PKEY_free(xk);
155280304Sjkim    return (ok);
156280304Sjkim}
157160814Ssimon
158280304Sjkim/*
159280304Sjkim * It seems several organisations had the same idea of including a list of
16059191Skris * extensions in a certificate request. There are at least two OIDs that are
16159191Skris * used and there may be more: so the list is configurable.
16259191Skris */
16359191Skris
164280304Sjkimstatic int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef };
16559191Skris
16659191Skrisstatic int *ext_nids = ext_nid_list;
16759191Skris
16859191Skrisint X509_REQ_extension_nid(int req_nid)
16959191Skris{
170280304Sjkim    int i, nid;
171280304Sjkim    for (i = 0;; i++) {
172280304Sjkim        nid = ext_nids[i];
173280304Sjkim        if (nid == NID_undef)
174280304Sjkim            return 0;
175280304Sjkim        else if (req_nid == nid)
176280304Sjkim            return 1;
177280304Sjkim    }
17859191Skris}
17959191Skris
18059191Skrisint *X509_REQ_get_extension_nids(void)
18159191Skris{
182280304Sjkim    return ext_nids;
18359191Skris}
184280304Sjkim
18559191Skrisvoid X509_REQ_set_extension_nids(int *nids)
18659191Skris{
187280304Sjkim    ext_nids = nids;
18859191Skris}
18959191Skris
19059191SkrisSTACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
191280304Sjkim{
192280304Sjkim    X509_ATTRIBUTE *attr;
193280304Sjkim    ASN1_TYPE *ext = NULL;
194280304Sjkim    int idx, *pnid;
195280304Sjkim    const unsigned char *p;
196142425Snectar
197280304Sjkim    if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
198280304Sjkim        return (NULL);
199280304Sjkim    for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
200280304Sjkim        idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
201280304Sjkim        if (idx == -1)
202280304Sjkim            continue;
203280304Sjkim        attr = X509_REQ_get_attr(req, idx);
204280304Sjkim        if (attr->single)
205280304Sjkim            ext = attr->value.single;
206280304Sjkim        else if (sk_ASN1_TYPE_num(attr->value.set))
207280304Sjkim            ext = sk_ASN1_TYPE_value(attr->value.set, 0);
208280304Sjkim        break;
209280304Sjkim    }
210280304Sjkim    if (!ext || (ext->type != V_ASN1_SEQUENCE))
211280304Sjkim        return NULL;
212280304Sjkim    p = ext->value.sequence->data;
213280304Sjkim    return (STACK_OF(X509_EXTENSION) *)
214280304Sjkim        ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
215280304Sjkim                      ASN1_ITEM_rptr(X509_EXTENSIONS));
216160814Ssimon}
21759191Skris
218280304Sjkim/*
219280304Sjkim * Add a STACK_OF extensions to a certificate request: allow alternative OIDs
22059191Skris * in case we want to create a non standard one.
22159191Skris */
22259191Skris
22359191Skrisint X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
224280304Sjkim                                int nid)
22559191Skris{
226280304Sjkim    ASN1_TYPE *at = NULL;
227280304Sjkim    X509_ATTRIBUTE *attr = NULL;
228280304Sjkim    if (!(at = ASN1_TYPE_new()) || !(at->value.sequence = ASN1_STRING_new()))
229280304Sjkim        goto err;
23059191Skris
231280304Sjkim    at->type = V_ASN1_SEQUENCE;
232280304Sjkim    /* Generate encoding of extensions */
233280304Sjkim    at->value.sequence->length =
234280304Sjkim        ASN1_item_i2d((ASN1_VALUE *)exts,
235280304Sjkim                      &at->value.sequence->data,
236280304Sjkim                      ASN1_ITEM_rptr(X509_EXTENSIONS));
237280304Sjkim    if (!(attr = X509_ATTRIBUTE_new()))
238280304Sjkim        goto err;
239280304Sjkim    if (!(attr->value.set = sk_ASN1_TYPE_new_null()))
240280304Sjkim        goto err;
241280304Sjkim    if (!sk_ASN1_TYPE_push(attr->value.set, at))
242280304Sjkim        goto err;
243280304Sjkim    at = NULL;
244280304Sjkim    attr->single = 0;
245280304Sjkim    attr->object = OBJ_nid2obj(nid);
246280304Sjkim    if (!req->req_info->attributes) {
247280304Sjkim        if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
248280304Sjkim            goto err;
249280304Sjkim    }
250280304Sjkim    if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr))
251280304Sjkim        goto err;
252280304Sjkim    return 1;
253280304Sjkim err:
254280304Sjkim    X509_ATTRIBUTE_free(attr);
255280304Sjkim    ASN1_TYPE_free(at);
256280304Sjkim    return 0;
25759191Skris}
258280304Sjkim
25959191Skris/* This is the normal usage: use the "official" OID */
26059191Skrisint X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
26159191Skris{
262280304Sjkim    return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
26359191Skris}
26459191Skris
26559191Skris/* Request attribute functions */
26659191Skris
26759191Skrisint X509_REQ_get_attr_count(const X509_REQ *req)
26859191Skris{
269280304Sjkim    return X509at_get_attr_count(req->req_info->attributes);
27059191Skris}
27159191Skris
272280304Sjkimint X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos)
27359191Skris{
274280304Sjkim    return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
27559191Skris}
27659191Skris
27759191Skrisint X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
278280304Sjkim                             int lastpos)
27959191Skris{
280280304Sjkim    return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
28159191Skris}
28259191Skris
28359191SkrisX509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
28459191Skris{
285280304Sjkim    return X509at_get_attr(req->req_info->attributes, loc);
28659191Skris}
28759191Skris
28859191SkrisX509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
28959191Skris{
290280304Sjkim    return X509at_delete_attr(req->req_info->attributes, loc);
29159191Skris}
29259191Skris
29359191Skrisint X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
29459191Skris{
295280304Sjkim    if (X509at_add1_attr(&req->req_info->attributes, attr))
296280304Sjkim        return 1;
297280304Sjkim    return 0;
29859191Skris}
29959191Skris
30059191Skrisint X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
301280304Sjkim                              const ASN1_OBJECT *obj, int type,
302280304Sjkim                              const unsigned char *bytes, int len)
30359191Skris{
304280304Sjkim    if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
305280304Sjkim                                type, bytes, len))
306280304Sjkim        return 1;
307280304Sjkim    return 0;
30859191Skris}
30959191Skris
31059191Skrisint X509_REQ_add1_attr_by_NID(X509_REQ *req,
311280304Sjkim                              int nid, int type,
312280304Sjkim                              const unsigned char *bytes, int len)
31359191Skris{
314280304Sjkim    if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
315280304Sjkim                                type, bytes, len))
316280304Sjkim        return 1;
317280304Sjkim    return 0;
31859191Skris}
31959191Skris
32059191Skrisint X509_REQ_add1_attr_by_txt(X509_REQ *req,
321280304Sjkim                              const char *attrname, int type,
322280304Sjkim                              const unsigned char *bytes, int len)
32359191Skris{
324280304Sjkim    if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
325280304Sjkim                                type, bytes, len))
326280304Sjkim        return 1;
327280304Sjkim    return 0;
32859191Skris}
329