ASN1_ITEM versions of sign, verify, pack and unpack.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 28 Dec 2000 19:18:48 +0000 (19:18 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 28 Dec 2000 19:18:48 +0000 (19:18 +0000)
The old function pointer versions will eventually go
away.

CHANGES
crypto/asn1/a_digest.c
crypto/asn1/a_sign.c
crypto/asn1/a_verify.c
crypto/asn1/asn1.h
crypto/asn1/asn_pack.c
crypto/x509/x509.h

diff --git a/CHANGES b/CHANGES
index 193e9adea6c1336e6df519ffe3c8016bc9acdf84..d83e08ad4bbe2d24495d9894c150dfabf52020be 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,10 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) New ASN1 functions to handle sign, verify, digest, pack and
+     unpack operations in terms of ASN1_ITEM.
+     [Steve Henson]
+
   *) New extension functions for OCSP structures, these follow the
      same conventions as certificates and CRLs.
      [Steve Henson]
index 8257b8639e12f3a6fd2ec8204a93e79f9e06e4fa..fb4686fdbd17c4dfcb7bd93cadb2e377108df8bf 100644 (file)
@@ -88,3 +88,21 @@ int ASN1_digest(int (*i2d)(), const EVP_MD *type, char *data,
        return(1);
        }
 
+
+int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
+               unsigned char *md, unsigned int *len)
+       {
+       EVP_MD_CTX ctx;
+       int i;
+       unsigned char *str = NULL;
+
+       i=ASN1_item_i2d(asn,&str, it);
+       if (!str) return(0);
+
+       EVP_DigestInit(&ctx,type);
+       EVP_DigestUpdate(&ctx,str,i);
+       EVP_DigestFinal(&ctx,md,len);
+       OPENSSL_free(str);
+       return(1);
+       }
+
index 4c651706d2d6a2acfb345cb0661c2ef54fcef13a..5be077ddfc5a38519e7bf33c957c4a254c489518 100644 (file)
@@ -146,3 +146,76 @@ err:
                { memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); }
        return(outl);
        }
+
+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;
+
+       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(&ctx,type);
+       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:
+       memset(&ctx,0,sizeof(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);
+       }
index 2a11927e5c1c2a68e415dbda002f711dde730c41..be5a27e58b132645f2bf09df2c427084a7e57da0 100644 (file)
@@ -117,3 +117,51 @@ int ASN1_verify(int (*i2d)(), X509_ALGOR *a, ASN1_BIT_STRING *signature,
 err:
        return(ret);
        }
+
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature,
+            void *asn, EVP_PKEY *pkey)
+       {
+       EVP_MD_CTX ctx;
+       const EVP_MD *type;
+       unsigned char *buf_in=NULL;
+       int ret= -1,i,inl;
+
+       i=OBJ_obj2nid(a->algorithm);
+       type=EVP_get_digestbyname(OBJ_nid2sn(i));
+       if (type == NULL)
+               {
+               ASN1err(ASN1_F_ASN1_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+               goto err;
+               }
+
+       inl = ASN1_item_i2d(asn, &buf_in, it);
+       
+       if (buf_in == NULL)
+               {
+               ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       EVP_VerifyInit(&ctx,type);
+       EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl);
+
+       memset(buf_in,0,(unsigned int)inl);
+       OPENSSL_free(buf_in);
+
+       if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data,
+                       (unsigned int)signature->length,pkey) <= 0)
+               {
+               ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_EVP_LIB);
+               ret=0;
+               goto err;
+               }
+       /* we don't need to zero the 'ctx' because we just checked
+        * public information */
+       /* memset(&ctx,0,sizeof(ctx)); */
+       ret=1;
+err:
+       return(ret);
+       }
+
+
index 080bf713c097bb3e8cda038fc2bcee9e1abece17..902aebb0611e75d5b2f2759bdc4ce82a492ddb24 100644 (file)
@@ -852,7 +852,9 @@ STACK *ASN1_seq_unpack(unsigned char *buf, int len, char *(*d2i)(),
 unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf,
                             int *len );
 void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)());
+void *ASN1_unpack_item(ASN1_STRING *oct, const ASN1_ITEM *it);
 ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct);
+ASN1_STRING *ASN1_pack_item(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
 
 void ASN1_STRING_set_default_mask(unsigned long mask);
 int ASN1_STRING_set_default_mask_asc(char *p);
index bdf5f130b3a3cd0c5ad7540287ea956602cb5808..0b9ed691a9647fea7fe5778f3effd66b29f5c912 100644 (file)
@@ -117,7 +117,7 @@ void *ASN1_unpack_string (ASN1_STRING *oct, char *(*d2i)())
 
 /* Pack an ASN1 object into an ASN1_STRING */
 
-ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct)
+ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_STRING **oct)
 {
        unsigned char *p;
        ASN1_STRING *octmp;
@@ -143,3 +143,45 @@ ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct)
        return octmp;
 }
 
+/* ASN1_ITEM versions of the above */
+
+ASN1_STRING *ASN1_pack_item(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
+{
+       ASN1_STRING *octmp;
+
+       if (!oct || !*oct) {
+               if (!(octmp = ASN1_STRING_new ())) {
+                       ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE);
+                       return NULL;
+               }
+               if (oct) *oct = octmp;
+       } else octmp = *oct;
+
+       if(octmp->data) {
+               OPENSSL_free(octmp->data);
+               octmp->data = NULL;
+       }
+               
+       if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
+               ASN1err(ASN1_F_ASN1_PACK_STRING,ASN1_R_ENCODE_ERROR);
+               return NULL;
+       }
+       if (!octmp->data) {
+               ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE);
+               return NULL;
+       }
+       return octmp;
+}
+
+/* Extract an ASN1 object from an ASN1_STRING */
+
+void *ASN1_unpack_item(ASN1_STRING *oct, const ASN1_ITEM *it)
+{
+       unsigned char *p;
+       void *ret;
+
+       p = oct->data;
+       if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
+               ASN1err(ASN1_F_ASN1_UNPACK_STRING,ASN1_R_DECODE_ERROR);
+       return ret;
+}
index 24ba8618c2a7d64b3e44cb6fbd78eff5dd3dad33..332cad553ae817c93993f5dd3afa81e494b994ba 100644 (file)
@@ -913,6 +913,16 @@ int ASN1_digest(int (*i2d)(),const EVP_MD *type,char *data,
 int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2,
        ASN1_BIT_STRING *signature,
        char *data,EVP_PKEY *pkey, const EVP_MD *type);
+
+int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data,
+       unsigned char *md,unsigned int *len);
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
+       ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey);
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+       ASN1_BIT_STRING *signature,
+       void *data, EVP_PKEY *pkey, const EVP_MD *type);
 #endif
 
 int            X509_set_version(X509 *x,long version);