LCOV - code coverage report
Current view: top level - zxid - keygen.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 130 158 82.3 %
Date: 2010-12-19 Functions: 6 6 100.0 %
Branches: 67 142 47.2 %

           Branch data     Line data    Source code
       1                 :            : /* keygen.c  -  Key generation utilities. See smime.c for user interface.
       2                 :            :  *
       3                 :            :  * Copyright (c) 1999 Sampo Kellomaki <sampo@iki.fi>, All Rights Reserved.
       4                 :            :  * License: This software may be distributed under the same license
       5                 :            :  *          terms as openssl (i.e. free, but mandatory attribution).
       6                 :            :  *
       7                 :            :  * This borrows quite heavily ideas and control flow from openssl/apps/req.c
       8                 :            :  * by Eric A. Young. You could say this file is destillation of Eric's
       9                 :            :  * work with many of the parameters hard wired:
      10                 :            :  *
      11                 :            :  *   - 1024 bit RSA only
      12                 :            :  *   - 3DES for private key
      13                 :            :  *   - MD5 hash
      14                 :            :  *
      15                 :            :  * 27.9.1999, Created. --Sampo
      16                 :            :  * 30.9.1999, added PKCS12 stuff, --Sampo
      17                 :            :  * 1.10.1999, improved error reporting, --Sampo
      18                 :            :  * 6.10.1999, divided into keygen.c, pkcs12.c, and smime-qry.c --Sampo
      19                 :            :  * 9.10.1999, reviewed for double frees, --Sampo
      20                 :            :  */
      21                 :            : 
      22                 :            : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
      23                 :            :  * All rights reserved.
      24                 :            :  *
      25                 :            :  * This package is an SSL implementation written
      26                 :            :  * by Eric Young (eay@cryptsoft.com).
      27                 :            :  * The implementation was written so as to conform with Netscapes SSL.
      28                 :            :  * 
      29                 :            :  * This library is free for commercial and non-commercial use as long as
      30                 :            :  * the following conditions are aheared to.  The following conditions
      31                 :            :  * apply to all code found in this distribution, be it the RC4, RSA,
      32                 :            :  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
      33                 :            :  * included with this distribution is covered by the same copyright terms
      34                 :            :  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
      35                 :            :  * 
      36                 :            :  * Copyright remains Eric Young's, and as such any Copyright notices in
      37                 :            :  * the code are not to be removed.
      38                 :            :  * If this package is used in a product, Eric Young should be given attribution
      39                 :            :  * as the author of the parts of the library used.
      40                 :            :  * This can be in the form of a textual message at program startup or
      41                 :            :  * in documentation (online or textual) provided with the package.
      42                 :            :  * 
      43                 :            :  * Redistribution and use in source and binary forms, with or without
      44                 :            :  * modification, are permitted provided that the following conditions
      45                 :            :  * are met:
      46                 :            :  * 1. Redistributions of source code must retain the copyright
      47                 :            :  *    notice, this list of conditions and the following disclaimer.
      48                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      49                 :            :  *    notice, this list of conditions and the following disclaimer in the
      50                 :            :  *    documentation and/or other materials provided with the distribution.
      51                 :            :  * 3. All advertising materials mentioning features or use of this software
      52                 :            :  *    must display the following acknowledgement:
      53                 :            :  *    "This product includes cryptographic software written by
      54                 :            :  *     Eric Young (eay@cryptsoft.com)"
      55                 :            :  *    The word 'cryptographic' can be left out if the rouines from the library
      56                 :            :  *    being used are not cryptographic related :-).
      57                 :            :  * 4. If you include any Windows specific code (or a derivative thereof) from 
      58                 :            :  *   the apps directory (application code) you must include an acknowledgement:
      59                 :            :  *   "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
      60                 :            :  * 
      61                 :            :  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
      62                 :            :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      63                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      64                 :            :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      65                 :            :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      66                 :            :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      67                 :            :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      68                 :            :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      69                 :            :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      70                 :            :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      71                 :            :  * SUCH DAMAGE.
      72                 :            :  * 
      73                 :            :  * The licence and distribution terms for any publically available version or
      74                 :            :  * derivative of this code cannot be changed.  i.e. this code cannot simply be
      75                 :            :  * copied and put under another distribution licence
      76                 :            :  * [including the GNU Public Licence.]
      77                 :            :  */
      78                 :            : 
      79                 :            : #include "platform.h"
      80                 :            : #include <stdio.h>
      81                 :            : #include <string.h>
      82                 :            : #include <time.h>
      83                 :            : 
      84                 :            : #ifdef __MWERKS__
      85                 :            : # include "macglue.h"
      86                 :            : #endif
      87                 :            : 
      88                 :            : #include "logprint.h"
      89                 :            : 
      90                 :            : #include <openssl/crypto.h>
      91                 :            : #include <openssl/buffer.h>
      92                 :            : #include <openssl/err.h>
      93                 :            : #include <openssl/rand.h>
      94                 :            : #include <openssl/conf.h>
      95                 :            : #include <openssl/bio.h>
      96                 :            : #include <openssl/stack.h>
      97                 :            : #include <openssl/objects.h>
      98                 :            : #include <openssl/asn1.h>
      99                 :            : #include <openssl/pem.h>
     100                 :            : #include <openssl/evp.h>
     101                 :            : #include <openssl/x509.h>
     102                 :            : #include <openssl/x509v3.h>
     103                 :            : #include <openssl/pkcs12.h>
     104                 :            : 
     105                 :            : #define SMIME_INTERNALS  /* we want also our internal helper functions */
     106                 :            : #include "smimeutil.h"
     107                 :            : 
     108                 :            : /* Enforce some rules about possible characters for different attributes */
     109                 :            : 
     110                 :            : static int req_fix_data(int nid, int *type /*IN-OUT*/)
     111                 :          6 : {
     112   [ +  +  -  + ]:          6 :   switch (nid) {
     113                 :          2 :   case NID_pkcs9_emailAddress: *type=V_ASN1_IA5STRING; break;
     114                 :            :   case NID_commonName:
     115                 :            :   case NID_pkcs9_challengePassword:
     116         [ -  + ]:          2 :     if (*type == V_ASN1_IA5STRING)
     117                 :          0 :       *type=V_ASN1_T61STRING;
     118                 :          2 :     break;
     119                 :            :   case NID_pkcs9_unstructuredName:
     120         [ #  # ]:          0 :     if (*type == V_ASN1_T61STRING) {
     121                 :          0 :       GOTO_ERR("08 invalid characters in attribute value string");
     122                 :            :     } else
     123                 :          0 :       *type=V_ASN1_IA5STRING;
     124                 :            :     break;
     125                 :            :   }
     126                 :            :   
     127                 :          6 :   return 1;
     128                 :          0 : err:
     129                 :          0 :   return 0;
     130                 :            : }
     131                 :            : 
     132                 :            : /* Add an entry to distinguished name */
     133                 :            : 
     134                 :            : /* Called by:  populate_request */
     135                 :            : static int add_DN_object(X509_NAME *n, int nid, unsigned char *val)
     136                 :          4 : {
     137                 :          4 :   X509_NAME_ENTRY *ne=NULL;
     138                 :          4 :   int type = ASN1_PRINTABLE_type(val,-1 /* uses strlen() */);
     139                 :            :   
     140         [ +  - ]:          4 :   if (req_fix_data(nid, &type) == 0) goto err;
     141                 :            :   
     142         [ -  + ]:          4 :   if (!(ne=X509_NAME_ENTRY_create_by_NID(NULL, nid, type,
     143                 :            :                                          val, strlen((char*)val))))
     144                 :          0 :     GOTO_ERR("X509_NAME_ENTRY_create_by_NID");
     145         [ -  + ]:          4 :   if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
     146                 :          0 :     GOTO_ERR("X509_NAME_add_entry");
     147                 :            :   
     148                 :          4 :   X509_NAME_ENTRY_free(ne);
     149                 :          4 :   return 1;
     150                 :          0 : err:
     151         [ #  # ]:          0 :   if (ne != NULL) X509_NAME_ENTRY_free(ne);
     152                 :          0 :   return 0;
     153                 :            : }
     154                 :            : 
     155                 :            : /* attribute objects are more complicated because they can be multivalued */
     156                 :            : 
     157                 :            : /* Called by: */
     158                 :            : static int add_attribute_object(STACK_OF(X509_ATTRIBUTE) *n, int nid, unsigned char *val)
     159                 :          2 : {
     160                 :          2 :   X509_ATTRIBUTE *xa=NULL;
     161                 :          2 :   ASN1_BIT_STRING *bs=NULL;
     162                 :          2 :   ASN1_TYPE *at=NULL;
     163                 :            :   
     164                 :            :   /* add object plus value */
     165         [ -  + ]:          2 :   if ((xa=X509_ATTRIBUTE_new()) == NULL) GOTO_ERR("no memory?");
     166         [ -  + ]:          2 :   if ((xa->value.set=sk_ASN1_TYPE_new_null()) == NULL) GOTO_ERR("no memory?");
     167                 :            :   /*xa->single = 1; **** this may also be set on some versions */
     168                 :            :   
     169         [ +  - ]:          2 :   if (xa->object != NULL) ASN1_OBJECT_free(xa->object);
     170                 :          2 :   xa->object=OBJ_nid2obj(nid);
     171                 :            :   
     172         [ -  + ]:          2 :   if ((bs=ASN1_BIT_STRING_new()) == NULL) GOTO_ERR("no memory?");  
     173                 :          2 :   bs->type=ASN1_PRINTABLE_type(val,-1 /* use strlen() */);
     174                 :            :   
     175         [ +  - ]:          2 :   if (!req_fix_data(nid,&bs->type)) goto err;
     176                 :            :   
     177         [ -  + ]:          2 :   if (!ASN1_STRING_set(bs,val,strlen((char*)val)+1)) GOTO_ERR("no memory?");
     178         [ -  + ]:          2 :   if ((at=ASN1_TYPE_new()) == NULL) GOTO_ERR("no memory?");
     179                 :            : 
     180                 :          2 :   ASN1_TYPE_set(at,bs->type,(char *)bs);
     181                 :          2 :   sk_ASN1_TYPE_push(xa->value.set,at);
     182                 :          2 :   bs=NULL;
     183                 :          2 :   at=NULL;
     184                 :            :   /* only one item per attribute */
     185                 :            : 
     186         [ -  + ]:          2 :   if (!sk_X509_ATTRIBUTE_push(n,xa))
     187                 :          0 :     GOTO_ERR("sk_X509_ATTRIBUTE_push (no memory?)");
     188                 :          2 :   return 1;
     189                 :          0 : err:
     190         [ #  # ]:          0 :   if (xa != NULL) X509_ATTRIBUTE_free(xa);
     191         [ #  # ]:          0 :   if (at != NULL) ASN1_TYPE_free(at);
     192         [ #  # ]:          0 :   if (bs != NULL) ASN1_BIT_STRING_free(bs);
     193                 :          0 :   return 0;
     194                 :            : }
     195                 :            : 
     196                 :            : /* Construct req structure. Basically we expect dn and attr to
     197                 :            :  * be new line separated attribute lists, each line containing
     198                 :            :  * attribute=value pair (i.e. separated by first `='. Parse
     199                 :            :  * the strings and add items one by one.
     200                 :            :  */
     201                 :            : 
     202                 :            : #define LINESEP "|\015\012"
     203                 :            : 
     204                 :            : /* Called by:  keygen */
     205                 :            : static X509_REQ* populate_request(const unsigned char* dn, const unsigned char* attr)
     206                 :          2 : {
     207                 :          2 :   char* p = NULL;
     208                 :            :   char* t;  /* type, see objects.h LN macros for possibilities */
     209                 :            :   char* v;  /* value */  
     210                 :            :   int nid;
     211                 :          2 :   X509_REQ* req = NULL;
     212                 :            :   X509_REQ_INFO* ri;
     213                 :            :   
     214                 :            :   LOG_PRINT("populate");
     215         [ +  - ]:          2 :   if (!dn) goto err;
     216         [ -  + ]:          2 :   if (!(req=X509_REQ_new())) GOTO_ERR("no memory?");
     217                 :          2 :   ri=req->req_info;
     218                 :            : 
     219                 :            :   LOG_PRINT("populate: set version");
     220                 :            :   /* setup version number */
     221         [ -  + ]:          2 :   if (!ASN1_INTEGER_set(ri->version,0L /*version 1*/))
     222                 :          0 :     GOTO_ERR("ASN1_INTEGER_set");
     223                 :            :   
     224                 :            :   /* Add fields of distinguished name. strtok() alters the buffer,
     225                 :            :    * and so do I, so lets get some fresh memory to play with. */
     226                 :            :   
     227         [ -  + ]:          2 :   if (!(p = strdup((const char*)dn))) GOTO_ERR("no memory?");
     228                 :            :   
     229                 :            :   /*Log_malloc = Log2;*/
     230                 :            :   LOG_PRINT("populate: distinguished name");
     231                 :            :   
     232         [ +  + ]:          6 :   for (t = strtok(p, LINESEP); t; t = strtok(NULL, LINESEP)) {
     233                 :            :     LOG_PRINT2("populate strtok returned '%s'",t);
     234         [ -  + ]:          4 :     if (!(v = strchr(t, '='))) GOTO_ERR("09 missing `=' in DN attribute spec");
     235                 :            :     /* *** assumes strtok() has already scanned past this char */
     236                 :          4 :     *(v++)='\0';
     237                 :            :     LOG_PRINT3("DN: %s=%s",t,v);
     238                 :            :     /* If OBJ not recognised ignore it */
     239         [ -  + ]:          4 :     if ((nid=OBJ_txt2nid(t)) == NID_undef)
     240                 :          0 :       GOTO_ERR("06 Unregistered DN attribute name (OBJ_txt2nid)");
     241                 :            :     LOG_PRINT2("NID %x",nid);
     242         [ +  - ]:          4 :     if (!add_DN_object(ri->subject,nid,(unsigned char*)v)) goto err;
     243                 :            :     LOG_PRINT("DN object added");
     244                 :            :   }
     245                 :          2 :   OPENSSL_free(p);
     246                 :          2 :   p = NULL;
     247         [ -  + ]:          2 :   if (!attr) return req;
     248                 :            :   
     249                 :            :   LOG_PRINT("populate: attributes");
     250                 :            :   
     251                 :            :   /* Add attribute fields */
     252                 :            :   
     253         [ +  - ]:          2 :   if (!(p = strdup((const char*)attr))) goto err;
     254         [ +  + ]:          4 :   for (t = strtok(p, LINESEP); t; t = strtok(NULL, LINESEP)) {
     255         [ -  + ]:          2 :     if (!(v = strchr(t, '='))) GOTO_ERR("09 missing `=' in attribute spec");
     256                 :            :     /* *** assumes strtok() has already scanned past this char */
     257                 :          2 :     *(v++)='\0';
     258                 :            :     /* If OBJ not recognised ignore it */
     259         [ -  + ]:          2 :     if ((nid=OBJ_txt2nid(t)) == NID_undef)
     260                 :          0 :       GOTO_ERR("07 Unregistered attribute name (OBJ_txt2nid)");
     261                 :            :     LOG_PRINT3("attr: %s=%s",t,v);
     262         [ +  - ]:          2 :     if (!add_attribute_object(ri->attributes, nid, (unsigned char*)v))
     263                 :          0 :       goto err;
     264                 :            :   }
     265                 :          2 :   OPENSSL_free(p);
     266                 :            :   LOG_PRINT("populate: done");
     267                 :          2 :   return req;
     268                 :          0 : err:
     269         [ #  # ]:          0 :   if (p) OPENSSL_free(p);
     270         [ #  # ]:          0 :   if (req) X509_REQ_free(req);
     271                 :            :   LOG_PRINT("populate: error");
     272                 :          0 :   return NULL;
     273                 :            : }
     274                 :            : 
     275                 :            : /* ============= K E Y   G E N E R A T I O N ==============*/
     276                 :            : 
     277                 :            : /* char** values are out parameters. They return malloced values.
     278                 :            :  * passowrd is the password used
     279                 :            :  * to encrypt the private key. identifiaction is a newline separated list
     280                 :            :  * of attributes to include in certification request. Each line has
     281                 :            :  * format: `name=value\n'
     282                 :            :  */
     283                 :            : 
     284                 :            : /* Called by:  smime_keygen */
     285                 :            : int keygen(const char* dn, const char* attr, const char* comment,
     286                 :            :        EVP_PKEY** pkey_out,
     287                 :            :        X509** x509ss_out,
     288                 :            :        X509_REQ** req_out)
     289                 :          2 : {
     290                 :            :   time_t t;
     291                 :          2 :   X509*     x509ss=NULL;
     292                 :          2 :   X509_REQ* req=NULL;
     293                 :          2 :   EVP_PKEY* pkey=NULL;
     294                 :          2 :   EVP_PKEY* tmp_pkey=NULL;
     295                 :          2 :   RSA*      rsa=NULL;
     296                 :          2 :   int ret = -1;
     297                 :            :   
     298         [ +  - ]:          2 :   if (pkey_out) *pkey_out = NULL;
     299         [ +  - ]:          2 :   if (x509ss_out) *x509ss_out = NULL;
     300         [ +  - ]:          2 :   if (req_out) *req_out = NULL;
     301                 :          2 :   X509V3_add_standard_extensions();
     302                 :            :   
     303                 :            :   LOG_PRINT("keygen start");
     304                 :            :   
     305                 :          2 :   t = time(NULL);
     306                 :          2 :   RAND_seed(&t,sizeof(t));
     307                 :            : #ifdef WINDOWS
     308                 :            :   RAND_screen(); /* Loading video display memory into random state */
     309                 :            : #endif
     310                 :            :   
     311                 :            :   /* Here's the beef */
     312                 :            :   
     313         [ -  + ]:          2 :   if (!(pkey=EVP_PKEY_new())) GOTO_ERR("no memory?");
     314                 :            :   LOG_PRINT("keygen preparing rsa key");
     315         [ -  + ]:          2 :   if (!(rsa = RSA_generate_key(1024 /*bits*/, 0x10001 /*65537*/,
     316                 :            :                                NULL /*req_cb*/, NULL /*arg*/)))
     317                 :          0 :      GOTO_ERR("RSA_generate_key");
     318                 :            :   LOG_PRINT("keygen rsa key generated");
     319         [ -  + ]:          2 :   if (!EVP_PKEY_assign_RSA(pkey, rsa)) GOTO_ERR("EVP_PKEY_assign_RSA");
     320         [ +  - ]:          2 :   if (pkey_out) *pkey_out = pkey;
     321                 :            :   
     322                 :          2 :   t = time(NULL);
     323                 :          2 :   RAND_seed(&t,sizeof(t));
     324                 :          2 :   RAND_write_file(randomfile);  /* Key generation is a big operation. Write
     325                 :            :                                    in the new random state. */
     326                 :            :   
     327                 :            :   /* ============================================================
     328                 :            :    * Now handle the public key part, i.e. create self signed and
     329                 :            :    * certificate request. This starts by making a request that
     330                 :            :    * contains all relevant fields.
     331                 :            :    */
     332                 :            :   
     333                 :            :   LOG_PRINT3("keygen populating request '%s' '%s'", dn, attr);
     334         [ -  + ]:          2 :   if (!(req=populate_request((const unsigned char*)dn,
     335                 :          0 :                              (const unsigned char*)attr))) goto err;
     336                 :            :   LOG_PRINT("keygen request populated");
     337                 :          2 :   X509_REQ_set_pubkey(req,pkey);
     338                 :            :   /*req->req_info->req_kludge=0;    / * no asn1 kludge *** filed deleted as of 0.9.7b?!? */
     339                 :            :   
     340         [ +  - ]:          2 :   if (req_out) {
     341                 :            :     LOG_PRINT("keygen signing request");
     342         [ -  + ]:          2 :     if (!(X509_REQ_sign(req, pkey, EVP_md5()))) GOTO_ERR("X509_REQ_sign");
     343                 :            :     LOG_PRINT("keygen request signed");
     344                 :          2 :     *req_out = req;
     345                 :            :   }
     346                 :            :   
     347                 :            : #if 1
     348                 :            :   /* -- X509 create self signed certificate */
     349                 :            :   
     350         [ +  - ]:          2 :   if (x509ss_out) {
     351                 :            :     LOG_PRINT("keygen making x509");
     352         [ -  + ]:          2 :     if (!(x509ss=X509_new())) GOTO_ERR("no memory?");
     353                 :            :     
     354                 :            :     /* Set version to V3 and serial number to zero */
     355         [ -  + ]:          2 :     if(!X509_set_version(x509ss, 2)) GOTO_ERR("X509_set_version");
     356                 :          2 :     ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L);
     357                 :            :     LOG_PRINT("keygen setting various x509 fields");
     358                 :            :     
     359                 :          2 :     X509_set_issuer_name(x509ss,
     360                 :            :                          X509_REQ_get_subject_name(req));
     361                 :          2 :     X509_gmtime_adj(X509_get_notBefore(x509ss),0);
     362                 :          2 :     X509_gmtime_adj(X509_get_notAfter(x509ss),
     363                 :            :                     (long)60*60*24*365 /*days*/);
     364                 :          2 :     X509_set_subject_name(x509ss,
     365                 :            :                           X509_REQ_get_subject_name(req));
     366                 :            :     
     367                 :            :     LOG_PRINT("keygen setting x509 attributes");
     368         [ -  + ]:          2 :     if (!(tmp_pkey =X509_REQ_get_pubkey(req))) GOTO_ERR("X509_REQ_get_pubkey");
     369                 :          2 :     X509_set_pubkey(x509ss,tmp_pkey);
     370                 :          2 :     EVP_PKEY_free(tmp_pkey);
     371                 :          2 :     tmp_pkey = NULL;
     372                 :            :     
     373                 :            :     /* Set up V3 context struct and add certificate extensions. Note
     374                 :            :      * that we need to add (full) suite of CA extensions, otherwise
     375                 :            :      * our cert is not valid for signing itself.
     376                 :            :      */
     377                 :            :     
     378         [ -  + ]:          2 :     if (add_some_X509v3_extensions(x509ss,
     379                 :            :                                    "CA:TRUE,pathlen:3", /*basic_constraints*/
     380                 :            :                                    "client,server,email,objsign,sslCA,emailCA,objCA", /*cert_type*/
     381                 :            :                                    "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign", /*key_usage*/
     382                 :          0 :                                    comment)==-1) goto err;
     383                 :            :     
     384                 :            :     LOG_PRINT("keygen signing x509");
     385         [ -  + ]:          2 :     if (!(X509_sign(x509ss, pkey, EVP_md5()))) GOTO_ERR("X509_sign");
     386                 :            :     LOG_PRINT("keygen x509 ready");
     387                 :          2 :     *x509ss_out = x509ss;
     388                 :            :   }
     389                 :            : #endif
     390                 :            :   
     391                 :          2 :   ret = 0;
     392                 :            :   
     393                 :          2 : err:
     394                 :            :   /*if (tmp_pkey)            EVP_PKEY_free(tmp_pkey); never happens */
     395   [ +  -  -  + ]:          2 :   if (pkey   && !pkey_out)   EVP_PKEY_free(pkey);
     396   [ +  -  -  + ]:          2 :   if (req    && !req_out)    X509_REQ_free(req);
     397   [ +  -  -  + ]:          2 :   if (x509ss && !x509ss_out) X509_free(x509ss);
     398                 :          2 :   X509V3_EXT_cleanup();
     399                 :          2 :   OBJ_cleanup();
     400                 :            :   LOG_PRINT("keygen done.");
     401                 :          2 :   return ret;
     402                 :            : }
     403                 :            : 
     404                 :            : /* Called by:  main */
     405                 :            : int smime_keygen(const char* dn, const char* attr, const char* passwd, const char* comment, char** priv_out, char** x509ss_out, char** request_out)
     406                 :          2 : {
     407                 :          2 :   X509*     x509ss=NULL;
     408                 :          2 :   X509_REQ* req=NULL;
     409                 :          2 :   EVP_PKEY* pkey=NULL;
     410                 :          2 :   int ret = -1;
     411                 :            : 
     412         [ +  - ]:          2 :   if (priv_out) *priv_out = NULL;
     413         [ +  - ]:          2 :   if (x509ss_out) *x509ss_out = NULL;
     414         [ +  - ]:          2 :   if (request_out) *request_out = NULL;
     415                 :            :   
     416         [ +  - ]:          2 :   if (keygen(dn, attr, comment, &pkey, &x509ss, &req) == -1) goto err;
     417                 :            :   
     418                 :            :   /* Write private key to file. While its being
     419                 :            :    * written, it will also get encrypted. */
     420                 :            :   
     421   [ +  -  +  - ]:          2 :   if (passwd && priv_out) {
     422         [ +  - ]:          2 :     if (write_private_key(pkey, passwd, priv_out) == -1) goto err;
     423                 :          2 :     EVP_PKEY_free(pkey);  /* free early so memory can be reused */
     424                 :          2 :     pkey = NULL;
     425                 :            :   }
     426                 :            :   
     427         [ +  - ]:          2 :   if (request_out) {
     428         [ +  - ]:          2 :     if (write_request(req, request_out) == -1) goto err;
     429                 :          2 :     X509_REQ_free(req);  /* free early so memory can be reused */
     430                 :          2 :     req = NULL;
     431                 :            :   }
     432                 :            :   
     433         [ +  - ]:          2 :   if (x509ss_out) {    
     434         [ +  - ]:          2 :     if (write_certificate(x509ss, x509ss_out)==-1) goto err;
     435                 :            :   }
     436                 :            :   
     437                 :          2 :   ret = 0;
     438                 :            :   
     439                 :          2 : err:
     440         [ -  + ]:          2 :   if (pkey)   EVP_PKEY_free(pkey);
     441         [ -  + ]:          2 :   if (req)    X509_REQ_free(req);
     442         [ +  - ]:          2 :   if (x509ss) X509_free(x509ss);
     443                 :          2 :   return ret;
     444                 :            : }
     445                 :            : 
     446                 :            : /* EOF  -  keygen.c */

Generated by: LCOV version 1.9