OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
x509_req.c
Go to the documentation of this file.
1 /* crypto/x509/x509_req.c */
2 /* Copyright (C) 1995-1998 Eric Young ([email protected])
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young ([email protected]).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to. The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson ([email protected]).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  * notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  * notice, this list of conditions and the following disclaimer in the
30  * documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  * must display the following acknowledgement:
33  * "This product includes cryptographic software written by
34  * Eric Young ([email protected])"
35  * The word 'cryptographic' can be left out if the rouines from the library
36  * being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  * the apps directory (application code) you must include an acknowledgement:
39  * "This product includes software written by Tim Hudson ([email protected])"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed. i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/bn.h>
62 #include <openssl/evp.h>
63 #include <openssl/asn1.h>
64 #include <openssl/asn1t.h>
65 #include <openssl/x509.h>
66 #include <openssl/objects.h>
67 #include <openssl/buffer.h>
68 #include <openssl/pem.h>
69 
71  {
72  X509_REQ *ret;
73  X509_REQ_INFO *ri;
74  int i;
75  EVP_PKEY *pktmp;
76 
77  ret=X509_REQ_new();
78  if (ret == NULL)
79  {
81  goto err;
82  }
83 
84  ri=ret->req_info;
85 
86  ri->version->length=1;
87  ri->version->data=(unsigned char *)OPENSSL_malloc(1);
88  if (ri->version->data == NULL) goto err;
89  ri->version->data[0]=0; /* version == 0 */
90 
92  goto err;
93 
94  pktmp = X509_get_pubkey(x);
95  i=X509_REQ_set_pubkey(ret,pktmp);
96  EVP_PKEY_free(pktmp);
97  if (!i) goto err;
98 
99  if (pkey != NULL)
100  {
101  if (!X509_REQ_sign(ret,pkey,md))
102  goto err;
103  }
104  return(ret);
105 err:
106  X509_REQ_free(ret);
107  return(NULL);
108  }
109 
111  {
112  if ((req == NULL) || (req->req_info == NULL))
113  return(NULL);
114  return(X509_PUBKEY_get(req->req_info->pubkey));
115  }
116 
118  {
119  EVP_PKEY *xk=NULL;
120  int ok=0;
121 
122  xk=X509_REQ_get_pubkey(x);
123  switch (EVP_PKEY_cmp(xk, k))
124  {
125  case 1:
126  ok=1;
127  break;
128  case 0:
130  break;
131  case -1:
133  break;
134  case -2:
135 #ifndef OPENSSL_NO_EC
136  if (k->type == EVP_PKEY_EC)
137  {
139  break;
140  }
141 #endif
142 #ifndef OPENSSL_NO_DH
143  if (k->type == EVP_PKEY_DH)
144  {
145  /* No idea */
147  break;
148  }
149 #endif
151  }
152 
153  EVP_PKEY_free(xk);
154  return(ok);
155  }
156 
157 /* It seems several organisations had the same idea of including a list of
158  * extensions in a certificate request. There are at least two OIDs that are
159  * used and there may be more: so the list is configurable.
160  */
161 
162 static int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef};
163 
164 static int *ext_nids = ext_nid_list;
165 
166 int X509_REQ_extension_nid(int req_nid)
167 {
168  int i, nid;
169  for(i = 0; ; i++) {
170  nid = ext_nids[i];
171  if(nid == NID_undef) return 0;
172  else if (req_nid == nid) return 1;
173  }
174 }
175 
177 {
178  return ext_nids;
179 }
180 
182 {
183  ext_nids = nids;
184 }
185 
186 STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
187  {
189  ASN1_TYPE *ext = NULL;
190  int idx, *pnid;
191  const unsigned char *p;
192 
193  if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
194  return(NULL);
195  for (pnid = ext_nids; *pnid != NID_undef; pnid++)
196  {
197  idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
198  if (idx == -1)
199  continue;
200  attr = X509_REQ_get_attr(req, idx);
201  if(attr->single) ext = attr->value.single;
202  else if(sk_ASN1_TYPE_num(attr->value.set))
203  ext = sk_ASN1_TYPE_value(attr->value.set, 0);
204  break;
205  }
206  if(!ext || (ext->type != V_ASN1_SEQUENCE))
207  return NULL;
208  p = ext->value.sequence->data;
209  return (STACK_OF(X509_EXTENSION) *)
210  ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
211  ASN1_ITEM_rptr(X509_EXTENSIONS));
212 }
213 
214 /* Add a STACK_OF extensions to a certificate request: allow alternative OIDs
215  * in case we want to create a non standard one.
216  */
217 
219  int nid)
220 {
221  ASN1_TYPE *at = NULL;
222  X509_ATTRIBUTE *attr = NULL;
223  if(!(at = ASN1_TYPE_new()) ||
224  !(at->value.sequence = ASN1_STRING_new())) goto err;
225 
226  at->type = V_ASN1_SEQUENCE;
227  /* Generate encoding of extensions */
228  at->value.sequence->length =
229  ASN1_item_i2d((ASN1_VALUE *)exts,
230  &at->value.sequence->data,
231  ASN1_ITEM_rptr(X509_EXTENSIONS));
232  if(!(attr = X509_ATTRIBUTE_new())) goto err;
233  if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
234  if(!sk_ASN1_TYPE_push(attr->value.set, at)) goto err;
235  at = NULL;
236  attr->single = 0;
237  attr->object = OBJ_nid2obj(nid);
238  if (!req->req_info->attributes)
239  {
240  if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
241  goto err;
242  }
243  if(!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) goto err;
244  return 1;
245  err:
246  X509_ATTRIBUTE_free(attr);
247  ASN1_TYPE_free(at);
248  return 0;
249 }
250 /* This is the normal usage: use the "official" OID */
252 {
253  return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
254 }
255 
256 /* Request attribute functions */
257 
259 {
260  return X509at_get_attr_count(req->req_info->attributes);
261 }
262 
264  int lastpos)
265 {
266  return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
267 }
268 
270  int lastpos)
271 {
272  return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
273 }
274 
276 {
277  return X509at_get_attr(req->req_info->attributes, loc);
278 }
279 
281 {
282  return X509at_delete_attr(req->req_info->attributes, loc);
283 }
284 
286 {
287  if(X509at_add1_attr(&req->req_info->attributes, attr)) return 1;
288  return 0;
289 }
290 
292  const ASN1_OBJECT *obj, int type,
293  const unsigned char *bytes, int len)
294 {
295  if(X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
296  type, bytes, len)) return 1;
297  return 0;
298 }
299 
301  int nid, int type,
302  const unsigned char *bytes, int len)
303 {
304  if(X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
305  type, bytes, len)) return 1;
306  return 0;
307 }
308 
310  const char *attrname, int type,
311  const unsigned char *bytes, int len)
312 {
313  if(X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
314  type, bytes, len)) return 1;
315  return 0;
316 }