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