summaryrefslogtreecommitdiffstats
path: root/crypto/openssl/apps/req.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssl/apps/req.c')
-rw-r--r--crypto/openssl/apps/req.c228
1 files changed, 180 insertions, 48 deletions
diff --git a/crypto/openssl/apps/req.c b/crypto/openssl/apps/req.c
index 046bb3d..f58e65e 100644
--- a/crypto/openssl/apps/req.c
+++ b/crypto/openssl/apps/req.c
@@ -56,6 +56,12 @@
* [including the GNU Public Licence.]
*/
+/* Until the key-gen callbacks are modified to use newer prototypes, we allow
+ * deprecated functions for openssl-internal code */
+#ifdef OPENSSL_NO_DEPRECATED
+#undef OPENSSL_NO_DEPRECATED
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -73,7 +79,13 @@
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
-#include "../crypto/cryptlib.h"
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
#define SECTION "req"
@@ -113,9 +125,10 @@
* require. This format is wrong
*/
-static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs,
- unsigned long chtype);
-static int build_subject(X509_REQ *req, char *subj, unsigned long chtype);
+static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int mutlirdn,
+ int attribs,unsigned long chtype);
+static int build_subject(X509_REQ *req, char *subj, unsigned long chtype,
+ int multirdn);
static int prompt_info(X509_REQ *req,
STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs,
@@ -123,16 +136,16 @@ static int prompt_info(X509_REQ *req,
static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
STACK_OF(CONF_VALUE) *attr, int attribs,
unsigned long chtype);
-static int add_attribute_object(X509_REQ *req, char *text,
- char *def, char *value, int nid, int n_min,
+static int add_attribute_object(X509_REQ *req, char *text, const char *def,
+ char *value, int nid, int n_min,
int n_max, unsigned long chtype);
-static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
- int nid,int n_min,int n_max, unsigned long chtype);
+static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value,
+ int nid,int n_min,int n_max, unsigned long chtype, int mval);
#ifndef OPENSSL_NO_RSA
-static void MS_CALLBACK req_cb(int p,int n,void *arg);
+static int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb);
#endif
static int req_check_len(int len,int n_min,int n_max);
-static int check_end(char *str, char *end);
+static int check_end(const char *str, const char *end);
#ifndef MONOLITH
static char *default_config_file=NULL;
#endif
@@ -142,6 +155,7 @@ static int batch=0;
#define TYPE_RSA 1
#define TYPE_DSA 2
#define TYPE_DH 3
+#define TYPE_EC 4
int MAIN(int, char **);
@@ -151,6 +165,9 @@ int MAIN(int argc, char **argv)
#ifndef OPENSSL_NO_DSA
DSA *dsa_params=NULL;
#endif
+#ifndef OPENSSL_NO_ECDSA
+ EC_KEY *ec_params = NULL;
+#endif
unsigned long nmflag = 0, reqflag = 0;
int ex=1,x509=0,days=30;
X509 *x509ss=NULL;
@@ -175,7 +192,8 @@ int MAIN(int argc, char **argv)
char *passin = NULL, *passout = NULL;
char *p;
char *subj = NULL;
- const EVP_MD *md_alg=NULL,*digest=EVP_md5();
+ int multirdn = 0;
+ const EVP_MD *md_alg=NULL,*digest=EVP_sha1();
unsigned long chtype = MBSTRING_ASC;
#ifndef MONOLITH
char *to_free;
@@ -322,11 +340,64 @@ int MAIN(int argc, char **argv)
}
}
BIO_free(in);
- newkey=BN_num_bits(dsa_params->p);
in=NULL;
+ newkey=BN_num_bits(dsa_params->p);
}
else
#endif
+#ifndef OPENSSL_NO_ECDSA
+ if (strncmp("ec:",p,3) == 0)
+ {
+ X509 *xtmp=NULL;
+ EVP_PKEY *dtmp;
+ EC_GROUP *group;
+
+ pkey_type=TYPE_EC;
+ p+=3;
+ if ((in=BIO_new_file(p,"r")) == NULL)
+ {
+ perror(p);
+ goto end;
+ }
+ if ((ec_params = EC_KEY_new()) == NULL)
+ goto end;
+ group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
+ if (group == NULL)
+ {
+ EC_KEY_free(ec_params);
+ ERR_clear_error();
+ (void)BIO_reset(in);
+ if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
+ {
+ BIO_printf(bio_err,"unable to load EC parameters from file\n");
+ goto end;
+ }
+
+ if ((dtmp=X509_get_pubkey(xtmp))==NULL)
+ goto end;
+ if (dtmp->type == EVP_PKEY_EC)
+ ec_params = EC_KEY_dup(dtmp->pkey.ec);
+ EVP_PKEY_free(dtmp);
+ X509_free(xtmp);
+ if (ec_params == NULL)
+ {
+ BIO_printf(bio_err,"Certificate does not contain EC parameters\n");
+ goto end;
+ }
+ }
+ else
+ {
+ if (EC_KEY_set_group(ec_params, group) == 0)
+ goto end;
+ EC_GROUP_free(group);
+ }
+
+ BIO_free(in);
+ in=NULL;
+ newkey = EC_GROUP_get_degree(EC_KEY_get0_group(ec_params));
+ }
+ else
+#endif
#ifndef OPENSSL_NO_DH
if (strncmp("dh:",p,4) == 0)
{
@@ -335,7 +406,9 @@ int MAIN(int argc, char **argv)
}
else
#endif
- pkey_type=TYPE_RSA;
+ {
+ goto bad;
+ }
newreq=1;
}
@@ -380,6 +453,8 @@ int MAIN(int argc, char **argv)
if (--argc < 1) goto bad;
subj= *(++argv);
}
+ else if (strcmp(*argv,"-multivalue-rdn") == 0)
+ multirdn=1;
else if (strcmp(*argv,"-days") == 0)
{
if (--argc < 1) goto bad;
@@ -445,9 +520,13 @@ bad:
BIO_printf(bio_err," the random number generator\n");
BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
+#ifndef OPENSSL_NO_ECDSA
+ BIO_printf(bio_err," -newkey ec:file generate a new EC key, parameters taken from CA in 'file'\n");
+#endif
BIO_printf(bio_err," -[digest] Digest to sign with (md5, sha1, md2, mdc2, md4)\n");
BIO_printf(bio_err," -config file request template file.\n");
BIO_printf(bio_err," -subj arg set or modify request subject\n");
+ BIO_printf(bio_err," -multivalue-rdn enable support for multivalued RDNs\n");
BIO_printf(bio_err," -new new request.\n");
BIO_printf(bio_err," -batch do not ask anything during request generation\n");
BIO_printf(bio_err," -x509 output a x509 structure instead of a cert. req.\n");
@@ -499,13 +578,16 @@ bad:
else
{
req_conf=config;
- if( verbose )
- BIO_printf(bio_err,"Using configuration from %s\n",
- default_config_file);
+
if (req_conf == NULL)
{
- BIO_printf(bio_err,"Unable to load config info\n");
+ BIO_printf(bio_err,"Unable to load config info from %s\n", default_config_file);
+ if (newreq)
+ goto end;
}
+ else if( verbose )
+ BIO_printf(bio_err,"Using configuration from %s\n",
+ default_config_file);
}
if (req_conf != NULL)
@@ -637,7 +719,8 @@ bad:
message */
goto end;
}
- if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
+ if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA ||
+ EVP_PKEY_type(pkey->type) == EVP_PKEY_EC)
{
char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE");
if (randfile == NULL)
@@ -648,6 +731,9 @@ bad:
if (newreq && (pkey == NULL))
{
+#ifndef OPENSSL_NO_RSA
+ BN_GENCB cb;
+#endif
char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE");
if (randfile == NULL)
ERR_clear_error();
@@ -661,24 +747,33 @@ bad:
newkey=DEFAULT_KEY_LENGTH;
}
- if (newkey < MIN_KEY_LENGTH)
+ if (newkey < MIN_KEY_LENGTH && (pkey_type == TYPE_RSA || pkey_type == TYPE_DSA))
{
BIO_printf(bio_err,"private key length is too short,\n");
- BIO_printf(bio_err,"it needs to be at least %d bits, not %d\n",MIN_KEY_LENGTH,newkey);
+ BIO_printf(bio_err,"it needs to be at least %d bits, not %ld\n",MIN_KEY_LENGTH,newkey);
goto end;
}
- BIO_printf(bio_err,"Generating a %d bit %s private key\n",
- newkey,(pkey_type == TYPE_RSA)?"RSA":"DSA");
+ BIO_printf(bio_err,"Generating a %ld bit %s private key\n",
+ newkey,(pkey_type == TYPE_RSA)?"RSA":
+ (pkey_type == TYPE_DSA)?"DSA":"EC");
if ((pkey=EVP_PKEY_new()) == NULL) goto end;
#ifndef OPENSSL_NO_RSA
+ BN_GENCB_set(&cb, req_cb, bio_err);
if (pkey_type == TYPE_RSA)
{
- if (!EVP_PKEY_assign_RSA(pkey,
- RSA_generate_key(newkey,0x10001,
- req_cb,bio_err)))
+ RSA *rsa = RSA_new();
+ BIGNUM *bn = BN_new();
+ if(!bn || !rsa || !BN_set_word(bn, 0x10001) ||
+ !RSA_generate_key_ex(rsa, newkey, bn, &cb) ||
+ !EVP_PKEY_assign_RSA(pkey, rsa))
+ {
+ if(bn) BN_free(bn);
+ if(rsa) RSA_free(rsa);
goto end;
+ }
+ BN_free(bn);
}
else
#endif
@@ -690,6 +785,15 @@ bad:
dsa_params=NULL;
}
#endif
+#ifndef OPENSSL_NO_ECDSA
+ if (pkey_type == TYPE_EC)
+ {
+ if (!EC_KEY_generate_key(ec_params)) goto end;
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec_params))
+ goto end;
+ ec_params = NULL;
+ }
+#endif
app_RAND_write_file(randfile, bio_err);
@@ -796,6 +900,10 @@ loop:
if (pkey->type == EVP_PKEY_DSA)
digest=EVP_dss1();
#endif
+#ifndef OPENSSL_NO_ECDSA
+ if (pkey->type == EVP_PKEY_EC)
+ digest=EVP_ecdsa();
+#endif
if (req == NULL)
{
req=X509_REQ_new();
@@ -804,7 +912,7 @@ loop:
goto end;
}
- i=make_REQ(req,pkey,subj,!x509, chtype);
+ i=make_REQ(req,pkey,subj,multirdn,!x509, chtype);
subj=NULL; /* done processing '-subj' option */
if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
{
@@ -899,7 +1007,7 @@ loop:
print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
}
- if (build_subject(req, subj, chtype) == 0)
+ if (build_subject(req, subj, chtype, multirdn) == 0)
{
BIO_printf(bio_err, "ERROR: cannot modify subject\n");
ex=1;
@@ -1083,12 +1191,15 @@ end:
#ifndef OPENSSL_NO_DSA
if (dsa_params != NULL) DSA_free(dsa_params);
#endif
+#ifndef OPENSSL_NO_ECDSA
+ if (ec_params != NULL) EC_KEY_free(ec_params);
+#endif
apps_shutdown();
OPENSSL_EXIT(ex);
}
-static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs,
- unsigned long chtype)
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
+ int attribs, unsigned long chtype)
{
int ret=0,i;
char no_prompt = 0;
@@ -1138,7 +1249,7 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs,
else
{
if (subj)
- i = build_subject(req, subj, chtype);
+ i = build_subject(req, subj, chtype, multirdn);
else
i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
}
@@ -1155,11 +1266,11 @@ err:
* subject is expected to be in the format /type0=value0/type1=value1/type2=...
* where characters may be escaped by \
*/
-static int build_subject(X509_REQ *req, char *subject, unsigned long chtype)
+static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, int multirdn)
{
X509_NAME *n;
- if (!(n = do_subject(subject, chtype)))
+ if (!(n = parse_name(subject, chtype, multirdn)))
return 0;
if (!X509_REQ_set_subject_name(req, n))
@@ -1180,9 +1291,10 @@ static int prompt_info(X509_REQ *req,
int i;
char *p,*q;
char buf[100];
- int nid;
+ int nid, mval;
long n_min,n_max;
- char *type,*def,*value;
+ char *type, *value;
+ const char *def;
CONF_VALUE *v;
X509_NAME *subj;
subj = X509_REQ_get_subject_name(req);
@@ -1223,10 +1335,17 @@ start: for (;;)
if(*p) type = p;
break;
}
+ if (*type == '+')
+ {
+ mval = -1;
+ type++;
+ }
+ else
+ mval = 0;
/* If OBJ not recognised ignore it */
if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
if (BIO_snprintf(buf,sizeof buf,"%s_default",v->name)
- >= sizeof buf)
+ >= (int)sizeof(buf))
{
BIO_printf(bio_err,"Name '%s' too long\n",v->name);
return 0;
@@ -1260,7 +1379,7 @@ start: for (;;)
}
if (!add_DN_object(subj,v->value,def,value,nid,
- n_min,n_max, chtype))
+ n_min,n_max, chtype, mval))
return 0;
}
if (X509_NAME_entry_count(subj) == 0)
@@ -1291,7 +1410,7 @@ start2: for (;;)
goto start2;
if (BIO_snprintf(buf,sizeof buf,"%s_default",type)
- >= sizeof buf)
+ >= (int)sizeof(buf))
{
BIO_printf(bio_err,"Name '%s' too long\n",v->name);
return 0;
@@ -1350,6 +1469,7 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
{
+ int mval;
v=sk_CONF_VALUE_value(dn_sk,i);
p=q=NULL;
type=v->name;
@@ -1366,8 +1486,19 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
if(*p) type = p;
break;
}
+#ifndef CHARSET_EBCDIC
+ if (*p == '+')
+#else
+ if (*p == os_toascii['+'])
+#endif
+ {
+ p++;
+ mval = -1;
+ }
+ else
+ mval = 0;
if (!X509_NAME_add_entry_by_txt(subj,type, chtype,
- (unsigned char *) v->value,-1,-1,0)) return 0;
+ (unsigned char *) v->value,-1,-1,mval)) return 0;
}
@@ -1389,8 +1520,8 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
}
-static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
- int nid, int n_min, int n_max, unsigned long chtype)
+static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value,
+ int nid, int n_min, int n_max, unsigned long chtype, int mval)
{
int i,ret=0;
MS_STATIC char buf[1024];
@@ -1439,14 +1570,14 @@ start:
#endif
if(!req_check_len(i, n_min, n_max)) goto start;
if (!X509_NAME_add_entry_by_NID(n,nid, chtype,
- (unsigned char *) buf, -1,-1,0)) goto err;
+ (unsigned char *) buf, -1,-1,mval)) goto err;
ret=1;
err:
return(ret);
}
-static int add_attribute_object(X509_REQ *req, char *text,
- char *def, char *value, int nid, int n_min,
+static int add_attribute_object(X509_REQ *req, char *text, const char *def,
+ char *value, int nid, int n_min,
int n_max, unsigned long chtype)
{
int i;
@@ -1510,7 +1641,7 @@ err:
}
#ifndef OPENSSL_NO_RSA
-static void MS_CALLBACK req_cb(int p, int n, void *arg)
+static int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb)
{
char c='*';
@@ -1518,11 +1649,12 @@ static void MS_CALLBACK req_cb(int p, int n, void *arg)
if (p == 1) c='+';
if (p == 2) c='*';
if (p == 3) c='\n';
- BIO_write((BIO *)arg,&c,1);
- (void)BIO_flush((BIO *)arg);
+ BIO_write(cb->arg,&c,1);
+ (void)BIO_flush(cb->arg);
#ifdef LINT
p=n;
#endif
+ return 1;
}
#endif
@@ -1542,10 +1674,10 @@ static int req_check_len(int len, int n_min, int n_max)
}
/* Check if the end of a string matches 'end' */
-static int check_end(char *str, char *end)
+static int check_end(const char *str, const char *end)
{
int elen, slen;
- char *tmp;
+ const char *tmp;
elen = strlen(end);
slen = strlen(str);
if(elen > slen) return 1;
OpenPOWER on IntegriCloud