1 /* crypto/pem/pem_seal.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 #include <openssl/opensslconf.h>  /* for OPENSSL_NO_RSA */
  60 #ifndef OPENSSL_NO_RSA
  61 #include <stdio.h>
  62 #include "cryptlib.h"
  63 #include <openssl/evp.h>
  64 #include <openssl/rand.h>
  65 #include <openssl/objects.h>
  66 #include <openssl/x509.h>
  67 #include <openssl/pem.h>
  68 #include <openssl/rsa.h>
  69 
  70 int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type,
  71              unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk,
  72              int npubk)
  73         {
  74         unsigned char key[EVP_MAX_KEY_LENGTH];
  75         int ret= -1;
  76         int i,j,max=0;
  77         char *s=NULL;
  78 
  79         for (i=0; i<npubk; i++)
  80                 {
  81                 if (pubk[i]->type != EVP_PKEY_RSA)
  82                         {
  83                         PEMerr(PEM_F_PEM_SEALINIT,PEM_R_PUBLIC_KEY_NO_RSA);
  84                         goto err;
  85                         }
  86                 j=RSA_size(pubk[i]->pkey.rsa);
  87                 if (j > max) max=j;
  88                 }
  89         s=(char *)OPENSSL_malloc(max*2);
  90         if (s == NULL)
  91                 {
  92                 PEMerr(PEM_F_PEM_SEALINIT,ERR_R_MALLOC_FAILURE);
  93                 goto err;
  94                 }
  95 
  96         EVP_EncodeInit(&ctx->encode);
  97 
  98         EVP_MD_CTX_init(&ctx->md);
  99         if (!EVP_SignInit(&ctx->md,md_type))
 100                 goto err;
 101 
 102         EVP_CIPHER_CTX_init(&ctx->cipher);
 103         ret=EVP_SealInit(&ctx->cipher,type,ek,ekl,iv,pubk,npubk);
 104         if (ret <= 0) goto err;
 105 
 106         /* base64 encode the keys */
 107         for (i=0; i<npubk; i++)
 108                 {
 109                 j=EVP_EncodeBlock((unsigned char *)s,ek[i],
 110                         RSA_size(pubk[i]->pkey.rsa));
 111                 ekl[i]=j;
 112                 memcpy(ek[i],s,j+1);
 113                 }
 114 
 115         ret=npubk;
 116 err:
 117         if (s != NULL) OPENSSL_free(s);
 118         OPENSSL_cleanse(key,EVP_MAX_KEY_LENGTH);
 119         return(ret);
 120         }
 121 
 122 void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl,
 123              unsigned char *in, int inl)
 124         {
 125         unsigned char buffer[1600];
 126         int i,j;
 127 
 128         *outl=0;
 129         EVP_SignUpdate(&ctx->md,in,inl);
 130         for (;;)
 131                 {
 132                 if (inl <= 0) break;
 133                 if (inl > 1200)
 134                         i=1200;
 135                 else
 136                         i=inl;
 137                 EVP_EncryptUpdate(&ctx->cipher,buffer,&j,in,i);
 138                 EVP_EncodeUpdate(&ctx->encode,out,&j,buffer,j);
 139                 *outl+=j;
 140                 out+=j;
 141                 in+=i;
 142                 inl-=i;
 143                 }
 144         }
 145 
 146 int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig, int *sigl,
 147              unsigned char *out, int *outl, EVP_PKEY *priv)
 148         {
 149         unsigned char *s=NULL;
 150         int ret=0,j;
 151         unsigned int i;
 152 
 153         if (priv->type != EVP_PKEY_RSA)
 154                 {
 155                 PEMerr(PEM_F_PEM_SEALFINAL,PEM_R_PUBLIC_KEY_NO_RSA);
 156                 goto err;
 157                 }
 158         i=RSA_size(priv->pkey.rsa);
 159         if (i < 100) i=100;
 160         s=(unsigned char *)OPENSSL_malloc(i*2);
 161         if (s == NULL)
 162                 {
 163                 PEMerr(PEM_F_PEM_SEALFINAL,ERR_R_MALLOC_FAILURE);
 164                 goto err;
 165                 }
 166 
 167         if (!EVP_EncryptFinal_ex(&ctx->cipher,s,(int *)&i))
 168                 goto err;
 169         EVP_EncodeUpdate(&ctx->encode,out,&j,s,i);
 170         *outl=j;
 171         out+=j;
 172         EVP_EncodeFinal(&ctx->encode,out,&j);
 173         *outl+=j;
 174 
 175         if (!EVP_SignFinal(&ctx->md,s,&i,priv)) goto err;
 176         *sigl=EVP_EncodeBlock(sig,s,i);
 177 
 178         ret=1;
 179 err:
 180         EVP_MD_CTX_cleanup(&ctx->md);
 181         EVP_CIPHER_CTX_cleanup(&ctx->cipher);
 182         if (s != NULL) OPENSSL_free(s);
 183         return(ret);
 184         }
 185 #else /* !OPENSSL_NO_RSA */
 186 
 187 # if PEDANTIC
 188 static void *dummy=&dummy;
 189 # endif
 190 
 191 #endif