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.
8296341Sdelphij *
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).
15296341Sdelphij *
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.
22296341Sdelphij *
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 :-).
37296341Sdelphij * 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)"
40296341Sdelphij *
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.
52296341Sdelphij *
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)
71296341Sdelphij{
72296341Sdelphij    X509_REQ *ret;
73296341Sdelphij    X509_REQ_INFO *ri;
74296341Sdelphij    int i;
75296341Sdelphij    EVP_PKEY *pktmp;
7655714Skris
77296341Sdelphij    ret = X509_REQ_new();
78296341Sdelphij    if (ret == NULL) {
79296341Sdelphij        X509err(X509_F_X509_TO_X509_REQ, ERR_R_MALLOC_FAILURE);
80296341Sdelphij        goto err;
81296341Sdelphij    }
8255714Skris
83296341Sdelphij    ri = ret->req_info;
8455714Skris
85296341Sdelphij    ri->version->length = 1;
86296341Sdelphij    ri->version->data = (unsigned char *)OPENSSL_malloc(1);
87296341Sdelphij    if (ri->version->data == NULL)
88296341Sdelphij        goto err;
89296341Sdelphij    ri->version->data[0] = 0;   /* version == 0 */
9055714Skris
91296341Sdelphij    if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x)))
92296341Sdelphij        goto err;
9355714Skris
94296341Sdelphij    pktmp = X509_get_pubkey(x);
95296341Sdelphij    if (pktmp == NULL)
96296341Sdelphij        goto err;
97296341Sdelphij    i = X509_REQ_set_pubkey(ret, pktmp);
98296341Sdelphij    EVP_PKEY_free(pktmp);
99296341Sdelphij    if (!i)
100296341Sdelphij        goto err;
10155714Skris
102296341Sdelphij    if (pkey != NULL) {
103296341Sdelphij        if (!X509_REQ_sign(ret, pkey, md))
104296341Sdelphij            goto err;
105296341Sdelphij    }
106296341Sdelphij    return (ret);
107296341Sdelphij err:
108296341Sdelphij    X509_REQ_free(ret);
109296341Sdelphij    return (NULL);
110296341Sdelphij}
11155714Skris
11255714SkrisEVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
113296341Sdelphij{
114296341Sdelphij    if ((req == NULL) || (req->req_info == NULL))
115296341Sdelphij        return (NULL);
116296341Sdelphij    return (X509_PUBKEY_get(req->req_info->pubkey));
117296341Sdelphij}
11855714Skris
119160814Ssimonint X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
120296341Sdelphij{
121296341Sdelphij    EVP_PKEY *xk = NULL;
122296341Sdelphij    int ok = 0;
123160814Ssimon
124296341Sdelphij    xk = X509_REQ_get_pubkey(x);
125296341Sdelphij    switch (EVP_PKEY_cmp(xk, k)) {
126296341Sdelphij    case 1:
127296341Sdelphij        ok = 1;
128296341Sdelphij        break;
129296341Sdelphij    case 0:
130296341Sdelphij        X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
131296341Sdelphij                X509_R_KEY_VALUES_MISMATCH);
132296341Sdelphij        break;
133296341Sdelphij    case -1:
134296341Sdelphij        X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH);
135296341Sdelphij        break;
136296341Sdelphij    case -2:
137160814Ssimon#ifndef OPENSSL_NO_EC
138296341Sdelphij        if (k->type == EVP_PKEY_EC) {
139296341Sdelphij            X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
140296341Sdelphij            break;
141296341Sdelphij        }
142160814Ssimon#endif
143160814Ssimon#ifndef OPENSSL_NO_DH
144296341Sdelphij        if (k->type == EVP_PKEY_DH) {
145296341Sdelphij            /* No idea */
146296341Sdelphij            X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
147296341Sdelphij                    X509_R_CANT_CHECK_DH_KEY);
148296341Sdelphij            break;
149296341Sdelphij        }
150160814Ssimon#endif
151296341Sdelphij        X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE);
152296341Sdelphij    }
153160814Ssimon
154296341Sdelphij    EVP_PKEY_free(xk);
155296341Sdelphij    return (ok);
156296341Sdelphij}
157160814Ssimon
158296341Sdelphij/*
159296341Sdelphij * 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
164296341Sdelphijstatic 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{
170296341Sdelphij    int i, nid;
171296341Sdelphij    for (i = 0;; i++) {
172296341Sdelphij        nid = ext_nids[i];
173296341Sdelphij        if (nid == NID_undef)
174296341Sdelphij            return 0;
175296341Sdelphij        else if (req_nid == nid)
176296341Sdelphij            return 1;
177296341Sdelphij    }
17859191Skris}
17959191Skris
18059191Skrisint *X509_REQ_get_extension_nids(void)
18159191Skris{
182296341Sdelphij    return ext_nids;
18359191Skris}
184296341Sdelphij
18559191Skrisvoid X509_REQ_set_extension_nids(int *nids)
18659191Skris{
187296341Sdelphij    ext_nids = nids;
18859191Skris}
18959191Skris
19059191SkrisSTACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
191296341Sdelphij{
192296341Sdelphij    X509_ATTRIBUTE *attr;
193296341Sdelphij    ASN1_TYPE *ext = NULL;
194296341Sdelphij    int idx, *pnid;
195296341Sdelphij    const unsigned char *p;
196142425Snectar
197296341Sdelphij    if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
198296341Sdelphij        return (NULL);
199296341Sdelphij    for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
200296341Sdelphij        idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
201296341Sdelphij        if (idx == -1)
202296341Sdelphij            continue;
203296341Sdelphij        attr = X509_REQ_get_attr(req, idx);
204296341Sdelphij        if (attr->single)
205296341Sdelphij            ext = attr->value.single;
206296341Sdelphij        else if (sk_ASN1_TYPE_num(attr->value.set))
207296341Sdelphij            ext = sk_ASN1_TYPE_value(attr->value.set, 0);
208296341Sdelphij        break;
209296341Sdelphij    }
210296341Sdelphij    if (!ext || (ext->type != V_ASN1_SEQUENCE))
211296341Sdelphij        return NULL;
212296341Sdelphij    p = ext->value.sequence->data;
213296341Sdelphij    return (STACK_OF(X509_EXTENSION) *)
214296341Sdelphij        ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
215296341Sdelphij                      ASN1_ITEM_rptr(X509_EXTENSIONS));
216160814Ssimon}
21759191Skris
218296341Sdelphij/*
219296341Sdelphij * 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,
224296341Sdelphij                                int nid)
22559191Skris{
226296341Sdelphij    ASN1_TYPE *at = NULL;
227296341Sdelphij    X509_ATTRIBUTE *attr = NULL;
228296341Sdelphij    if (!(at = ASN1_TYPE_new()) || !(at->value.sequence = ASN1_STRING_new()))
229296341Sdelphij        goto err;
23059191Skris
231296341Sdelphij    at->type = V_ASN1_SEQUENCE;
232296341Sdelphij    /* Generate encoding of extensions */
233296341Sdelphij    at->value.sequence->length =
234296341Sdelphij        ASN1_item_i2d((ASN1_VALUE *)exts,
235296341Sdelphij                      &at->value.sequence->data,
236296341Sdelphij                      ASN1_ITEM_rptr(X509_EXTENSIONS));
237296341Sdelphij    if (!(attr = X509_ATTRIBUTE_new()))
238296341Sdelphij        goto err;
239296341Sdelphij    if (!(attr->value.set = sk_ASN1_TYPE_new_null()))
240296341Sdelphij        goto err;
241296341Sdelphij    if (!sk_ASN1_TYPE_push(attr->value.set, at))
242296341Sdelphij        goto err;
243296341Sdelphij    at = NULL;
244296341Sdelphij    attr->single = 0;
245296341Sdelphij    attr->object = OBJ_nid2obj(nid);
246296341Sdelphij    if (!req->req_info->attributes) {
247296341Sdelphij        if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
248296341Sdelphij            goto err;
249296341Sdelphij    }
250296341Sdelphij    if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr))
251296341Sdelphij        goto err;
252296341Sdelphij    return 1;
253296341Sdelphij err:
254296341Sdelphij    X509_ATTRIBUTE_free(attr);
255296341Sdelphij    ASN1_TYPE_free(at);
256296341Sdelphij    return 0;
25759191Skris}
258296341Sdelphij
25959191Skris/* This is the normal usage: use the "official" OID */
26059191Skrisint X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
26159191Skris{
262296341Sdelphij    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{
269296341Sdelphij    return X509at_get_attr_count(req->req_info->attributes);
27059191Skris}
27159191Skris
272296341Sdelphijint X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos)
27359191Skris{
274296341Sdelphij    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,
278296341Sdelphij                             int lastpos)
27959191Skris{
280296341Sdelphij    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{
285296341Sdelphij    return X509at_get_attr(req->req_info->attributes, loc);
28659191Skris}
28759191Skris
28859191SkrisX509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
28959191Skris{
290296341Sdelphij    return X509at_delete_attr(req->req_info->attributes, loc);
29159191Skris}
29259191Skris
29359191Skrisint X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
29459191Skris{
295296341Sdelphij    if (X509at_add1_attr(&req->req_info->attributes, attr))
296296341Sdelphij        return 1;
297296341Sdelphij    return 0;
29859191Skris}
29959191Skris
30059191Skrisint X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
301296341Sdelphij                              const ASN1_OBJECT *obj, int type,
302296341Sdelphij                              const unsigned char *bytes, int len)
30359191Skris{
304296341Sdelphij    if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
305296341Sdelphij                                type, bytes, len))
306296341Sdelphij        return 1;
307296341Sdelphij    return 0;
30859191Skris}
30959191Skris
31059191Skrisint X509_REQ_add1_attr_by_NID(X509_REQ *req,
311296341Sdelphij                              int nid, int type,
312296341Sdelphij                              const unsigned char *bytes, int len)
31359191Skris{
314296341Sdelphij    if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
315296341Sdelphij                                type, bytes, len))
316296341Sdelphij        return 1;
317296341Sdelphij    return 0;
31859191Skris}
31959191Skris
32059191Skrisint X509_REQ_add1_attr_by_txt(X509_REQ *req,
321296341Sdelphij                              const char *attrname, int type,
322296341Sdelphij                              const unsigned char *bytes, int len)
32359191Skris{
324296341Sdelphij    if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
325296341Sdelphij                                type, bytes, len))
326296341Sdelphij        return 1;
327296341Sdelphij    return 0;
32859191Skris}
329