1 /* crypto/asn1/a_sign.c */
   2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
   3  * All rights reserved.
   4  *
   5  * This package is an SSL implementation written
   6  * by Eric Young (eay@cryptsoft.com).
   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 (tjh@cryptsoft.com).
  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 (eay@cryptsoft.com)"
  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 (tjh@cryptsoft.com)"
  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  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
  60  *
  61  * Redistribution and use in source and binary forms, with or without
  62  * modification, are permitted provided that the following conditions
  63  * are met:
  64  *
  65  * 1. Redistributions of source code must retain the above copyright
  66  *    notice, this list of conditions and the following disclaimer.
  67  *
  68  * 2. Redistributions in binary form must reproduce the above copyright
  69  *    notice, this list of conditions and the following disclaimer in
  70  *    the documentation and/or other materials provided with the
  71  *    distribution.
  72  *
  73  * 3. All advertising materials mentioning features or use of this
  74  *    software must display the following acknowledgment:
  75  *    "This product includes software developed by the OpenSSL Project
  76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  77  *
  78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  79  *    endorse or promote products derived from this software without
  80  *    prior written permission. For written permission, please contact
  81  *    openssl-core@openssl.org.
  82  *
  83  * 5. Products derived from this software may not be called "OpenSSL"
  84  *    nor may "OpenSSL" appear in their names without prior written
  85  *    permission of the OpenSSL Project.
  86  *
  87  * 6. Redistributions of any form whatsoever must retain the following
  88  *    acknowledgment:
  89  *    "This product includes software developed by the OpenSSL Project
  90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  91  *
  92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 103  * OF THE POSSIBILITY OF SUCH DAMAGE.
 104  * ====================================================================
 105  *
 106  * This product includes cryptographic software written by Eric Young
 107  * (eay@cryptsoft.com).  This product includes software written by Tim
 108  * Hudson (tjh@cryptsoft.com).
 109  *
 110  */
 111 
 112 #include <stdio.h>
 113 #include <time.h>
 114 
 115 #include "cryptlib.h"
 116 
 117 #ifndef NO_SYS_TYPES_H
 118 # include <sys/types.h>
 119 #endif
 120 
 121 #include <openssl/bn.h>
 122 #include <openssl/evp.h>
 123 #include <openssl/x509.h>
 124 #include <openssl/objects.h>
 125 #include <openssl/buffer.h>
 126 #include "asn1_locl.h"
 127 
 128 #ifndef NO_ASN1_OLD
 129 
 130 int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
 131               ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
 132               const EVP_MD *type)
 133         {
 134         EVP_MD_CTX ctx;
 135         unsigned char *p,*buf_in=NULL,*buf_out=NULL;
 136         int i,inl=0,outl=0,outll=0;
 137         X509_ALGOR *a;
 138 
 139         EVP_MD_CTX_init(&ctx);
 140         for (i=0; i<2; i++)
 141                 {
 142                 if (i == 0)
 143                         a=algor1;
 144                 else
 145                         a=algor2;
 146                 if (a == NULL) continue;
 147                 if (type->pkey_type == NID_dsaWithSHA1)
 148                         {
 149                         /* special case: RFC 2459 tells us to omit 'parameters'
 150                          * with id-dsa-with-sha1 */
 151                         ASN1_TYPE_free(a->parameter);
 152                         a->parameter = NULL;
 153                         }
 154                 else if ((a->parameter == NULL) ||
 155                         (a->parameter->type != V_ASN1_NULL))
 156                         {
 157                         ASN1_TYPE_free(a->parameter);
 158                         if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err;
 159                         a->parameter->type=V_ASN1_NULL;
 160                         }
 161                 ASN1_OBJECT_free(a->algorithm);
 162                 a->algorithm=OBJ_nid2obj(type->pkey_type);
 163                 if (a->algorithm == NULL)
 164                         {
 165                         ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_UNKNOWN_OBJECT_TYPE);
 166                         goto err;
 167                         }
 168                 if (a->algorithm->length == 0)
 169                         {
 170                         ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
 171                         goto err;
 172                         }
 173                 }
 174         inl=i2d(data,NULL);
 175         buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
 176         outll=outl=EVP_PKEY_size(pkey);
 177         buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
 178         if ((buf_in == NULL) || (buf_out == NULL))
 179                 {
 180                 outl=0;
 181                 ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE);
 182                 goto err;
 183                 }
 184         p=buf_in;
 185 
 186         i2d(data,&p);
 187         if (!EVP_SignInit_ex(&ctx,type, NULL)
 188                 || !EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl)
 189                 || !EVP_SignFinal(&ctx,(unsigned char *)buf_out,
 190                         (unsigned int *)&outl,pkey))
 191                 {
 192                 outl=0;
 193                 ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB);
 194                 goto err;
 195                 }
 196         if (signature->data != NULL) OPENSSL_free(signature->data);
 197         signature->data=buf_out;
 198         buf_out=NULL;
 199         signature->length=outl;
 200         /* In the interests of compatibility, I'll make sure that
 201          * the bit string has a 'not-used bits' value of 0
 202          */
 203         signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
 204         signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
 205 err:
 206         EVP_MD_CTX_cleanup(&ctx);
 207         if (buf_in != NULL)
 208                 { OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
 209         if (buf_out != NULL)
 210                 { OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
 211         return(outl);
 212         }
 213 
 214 #endif
 215 
 216 int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
 217              ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
 218              const EVP_MD *type)
 219         {
 220         EVP_MD_CTX ctx;
 221         EVP_MD_CTX_init(&ctx);
 222         if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey))
 223                 {
 224                 EVP_MD_CTX_cleanup(&ctx);
 225                 return 0;
 226                 }
 227         return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
 228         }
 229 
 230 
 231 int ASN1_item_sign_ctx(const ASN1_ITEM *it,
 232                 X509_ALGOR *algor1, X509_ALGOR *algor2,
 233                 ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
 234         {
 235         const EVP_MD *type;
 236         EVP_PKEY *pkey;
 237         unsigned char *buf_in=NULL,*buf_out=NULL;
 238         size_t inl=0,outl=0,outll=0;
 239         int signid, paramtype;
 240         int rv;
 241 
 242         type = EVP_MD_CTX_md(ctx);
 243         pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
 244 
 245         if (!type || !pkey)
 246                 {
 247                 ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
 248                 return 0;
 249                 }
 250 
 251         if (pkey->ameth->item_sign)
 252                 {
 253                 rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
 254                                                 signature);
 255                 if (rv == 1)
 256                         outl = signature->length;
 257                 /* Return value meanings:
 258                  * <=0: error.
 259                  *   1: method does everything.
 260                  *   2: carry on as normal.
 261                  *   3: ASN1 method sets algorithm identifiers: just sign.
 262                  */
 263                 if (rv <= 0)
 264                         ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
 265                 if (rv <= 1)
 266                         goto err;
 267                 }
 268         else
 269                 rv = 2;
 270 
 271         if (rv == 2)
 272                 {
 273                 if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
 274                         {
 275                         if (!pkey->ameth ||
 276                                 !OBJ_find_sigid_by_algs(&signid,
 277                                                         EVP_MD_nid(type),
 278                                                         pkey->ameth->pkey_id))
 279                                 {
 280                                 ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
 281                                         ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
 282                                 return 0;
 283                                 }
 284                         }
 285                 else
 286                         signid = type->pkey_type;
 287 
 288                 if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
 289                         paramtype = V_ASN1_NULL;
 290                 else
 291                         paramtype = V_ASN1_UNDEF;
 292 
 293                 if (algor1)
 294                         X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
 295                 if (algor2)
 296                         X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
 297 
 298                 }
 299 
 300         inl=ASN1_item_i2d(asn,&buf_in, it);
 301         outll=outl=EVP_PKEY_size(pkey);
 302         buf_out=OPENSSL_malloc((unsigned int)outl);
 303         if ((buf_in == NULL) || (buf_out == NULL))
 304                 {
 305                 outl=0;
 306                 ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_MALLOC_FAILURE);
 307                 goto err;
 308                 }
 309 
 310         if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
 311                 || !EVP_DigestSignFinal(ctx, buf_out, &outl))
 312                 {
 313                 outl=0;
 314                 ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_EVP_LIB);
 315                 goto err;
 316                 }
 317         if (signature->data != NULL) OPENSSL_free(signature->data);
 318         signature->data=buf_out;
 319         buf_out=NULL;
 320         signature->length=outl;
 321         /* In the interests of compatibility, I'll make sure that
 322          * the bit string has a 'not-used bits' value of 0
 323          */
 324         signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
 325         signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
 326 err:
 327         EVP_MD_CTX_cleanup(ctx);
 328         if (buf_in != NULL)
 329                 { OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
 330         if (buf_out != NULL)
 331                 { OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
 332         return(outl);
 333         }