Retain compatibility of EVP_DigestInit() and EVP_DigestFinal()
[openssl.git] / crypto / asn1 / a_sign.c
index eed7faaccb12850ff8d9c1a1c94363e97338494d..fc65b4ea5684f0e0da12668f6e4d062bf6da40e8 100644 (file)
@@ -71,6 +71,8 @@
 #include <openssl/objects.h>
 #include <openssl/buffer.h>
 
+#ifndef NO_ASN1_OLD
+
 int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2,
             ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
             const EVP_MD *type)
@@ -80,6 +82,7 @@ int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2,
        int i,inl=0,outl=0,outll=0;
        X509_ALGOR *a;
 
+       EVP_MD_CTX_init(&ctx);
        for (i=0; i<2; i++)
                {
                if (i == 0)
@@ -108,9 +111,9 @@ int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2,
                        }
                }
        inl=i2d(data,NULL);
-       buf_in=(unsigned char *)Malloc((unsigned int)inl);
+       buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
        outll=outl=EVP_PKEY_size(pkey);
-       buf_out=(unsigned char *)Malloc((unsigned int)outl);
+       buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
        if ((buf_in == NULL) || (buf_out == NULL))
                {
                outl=0;
@@ -120,7 +123,83 @@ int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2,
        p=buf_in;
 
        i2d(data,&p);
-       EVP_SignInit(&ctx,type);
+       EVP_SignInit_ex(&ctx,type, NULL);
+       EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl);
+       if (!EVP_SignFinal(&ctx,(unsigned char *)buf_out,
+                       (unsigned int *)&outl,pkey))
+               {
+               outl=0;
+               ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB);
+               goto err;
+               }
+       if (signature->data != NULL) OPENSSL_free(signature->data);
+       signature->data=buf_out;
+       buf_out=NULL;
+       signature->length=outl;
+       /* In the interests of compatibility, I'll make sure that
+        * the bit string has a 'not-used bits' value of 0
+        */
+       signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+       signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+err:
+       EVP_MD_CTX_cleanup(&ctx);
+       if (buf_in != NULL)
+               { memset((char *)buf_in,0,(unsigned int)inl); OPENSSL_free(buf_in); }
+       if (buf_out != NULL)
+               { memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); }
+       return(outl);
+       }
+
+#endif
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+            ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
+            const EVP_MD *type)
+       {
+       EVP_MD_CTX ctx;
+       unsigned char *buf_in=NULL,*buf_out=NULL;
+       int i,inl=0,outl=0,outll=0;
+       X509_ALGOR *a;
+
+       EVP_MD_CTX_init(&ctx);
+       for (i=0; i<2; i++)
+               {
+               if (i == 0)
+                       a=algor1;
+               else
+                       a=algor2;
+               if (a == NULL) continue;
+               if (    (a->parameter == NULL) || 
+                       (a->parameter->type != V_ASN1_NULL))
+                       {
+                       ASN1_TYPE_free(a->parameter);
+                       if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err;
+                       a->parameter->type=V_ASN1_NULL;
+                       }
+               ASN1_OBJECT_free(a->algorithm);
+               a->algorithm=OBJ_nid2obj(type->pkey_type);
+               if (a->algorithm == NULL)
+                       {
+                       ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_UNKNOWN_OBJECT_TYPE);
+                       goto err;
+                       }
+               if (a->algorithm->length == 0)
+                       {
+                       ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
+                       goto err;
+                       }
+               }
+       inl=ASN1_item_i2d(asn,&buf_in, it);
+       outll=outl=EVP_PKEY_size(pkey);
+       buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
+       if ((buf_in == NULL) || (buf_out == NULL))
+               {
+               outl=0;
+               ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       EVP_SignInit_ex(&ctx,type, NULL);
        EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl);
        if (!EVP_SignFinal(&ctx,(unsigned char *)buf_out,
                        (unsigned int *)&outl,pkey))
@@ -129,20 +208,20 @@ int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2,
                ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB);
                goto err;
                }
-       if (signature->data != NULL) Free((char *)signature->data);
+       if (signature->data != NULL) OPENSSL_free(signature->data);
        signature->data=buf_out;
        buf_out=NULL;
        signature->length=outl;
-       /* In the interests of compatability, I'll make sure that
+       /* In the interests of compatibility, I'll make sure that
         * the bit string has a 'not-used bits' value of 0
         */
        signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
        signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
 err:
-       memset(&ctx,0,sizeof(ctx));
+       EVP_MD_CTX_cleanup(&ctx);
        if (buf_in != NULL)
-               { memset((char *)buf_in,0,(unsigned int)inl); Free((char *)buf_in); }
+               { memset((char *)buf_in,0,(unsigned int)inl); OPENSSL_free(buf_in); }
        if (buf_out != NULL)
-               { memset((char *)buf_out,0,outll); Free((char *)buf_out); }
+               { memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); }
        return(outl);
        }