Commit 85522a07 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Algorithm specific ASN1 signing functions.

parent 31d66c2a
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4,6 +4,12 @@

 Changes between 1.0.0 and 1.1.0  [xx XXX xxxx]

  *) Support for companion algorithm specific ASN1 signing routines.
     New function ASN1_item_sign_ctx() signs a pre-initialised
     EVP_MD_CTX structure and sets AlgorithmIdentifiers based on
     the appropriate parameters.
     [Steve Henson]

  *) Add new algorithm specific ASN1 verification initialisation function
     to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1
     handling will be the same no matter what EVP_PKEY_METHOD is used.
+69 −33
Original line number Diff line number Diff line
@@ -218,30 +218,66 @@ int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
	     const EVP_MD *type)
	{
	EVP_MD_CTX ctx;
	EVP_MD_CTX_init(&ctx);
	if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey))
		{
		EVP_MD_CTX_cleanup(&ctx);
		return 0;
		}
	return ASN1_item_sign_ctx(&ctx, it, algor1, algor2, signature, asn);
	}
		

int ASN1_item_sign_ctx(EVP_MD_CTX *ctx,
		const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
	     	ASN1_BIT_STRING *signature, void *asn)
	{
	const EVP_MD *type;
	EVP_PKEY *pkey;
	unsigned char *buf_in=NULL,*buf_out=NULL;
	size_t inl=0,outl=0,outll=0;
	int signid, paramtype;
	int rv;

	if (type == NULL)
	type = EVP_MD_CTX_md(ctx);
	pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

	if (!type || !pkey)
		{
		int def_nid;
		if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
			type = EVP_get_digestbynid(def_nid);
		ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
		return 0;
		}

	if (type == NULL)
	if (pkey->ameth->item_sign)
		{
		ASN1err(ASN1_F_ASN1_ITEM_SIGN, ASN1_R_NO_DEFAULT_DIGEST);
		return 0;
		rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
						signature);
		if (rv == 1)
			outl = signature->length;
		/* Return value meanings:
		 * <=0: error.
		 *   1: method does everything.
		 *   2: carry on as normal.
		 *   3: ASN1 method sets algorithm identifiers: just sign.
		 */
		if (rv <= 0)
			ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
		if (rv <= 1)
			goto err;
		}
	else
		rv = 2;

	if (rv == 2)
		{
		if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
			{
			if (!pkey->ameth ||
			!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type),
				!OBJ_find_sigid_by_algs(&signid,
							EVP_MD_nid(type),
							pkey->ameth->pkey_id))
				{
			ASN1err(ASN1_F_ASN1_ITEM_SIGN,
				ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
					ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
				return 0;
				}
@@ -259,23 +295,23 @@ int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
		if (algor2)
			X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

	EVP_MD_CTX_init(&ctx);
		}

	inl=ASN1_item_i2d(asn,&buf_in, it);
	outll=outl=EVP_PKEY_size(pkey);
	buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
	buf_out=OPENSSL_malloc((unsigned int)outl);
	if ((buf_in == NULL) || (buf_out == NULL))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_ITEM_SIGN,ERR_R_MALLOC_FAILURE);
		ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)
		|| !EVP_DigestSignUpdate(&ctx, buf_in, inl)
		|| !EVP_DigestSignFinal(&ctx, buf_out, &outl))
	if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
		|| !EVP_DigestSignFinal(ctx, buf_out, &outl))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_ITEM_SIGN,ERR_R_EVP_LIB);
		ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_EVP_LIB);
		goto err;
		}
	if (signature->data != NULL) OPENSSL_free(signature->data);
@@ -288,7 +324,7 @@ int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
err:
	EVP_MD_CTX_cleanup(&ctx);
	EVP_MD_CTX_cleanup(ctx);
	if (buf_in != NULL)
		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
	if (buf_out != NULL)
+2 −0
Original line number Diff line number Diff line
@@ -1193,6 +1193,7 @@ void ERR_load_ASN1_strings(void);
#define ASN1_F_ASN1_ITEM_I2D_FP				 193
#define ASN1_F_ASN1_ITEM_PACK				 198
#define ASN1_F_ASN1_ITEM_SIGN				 195
#define ASN1_F_ASN1_ITEM_SIGN_CTX			 220
#define ASN1_F_ASN1_ITEM_UNPACK				 199
#define ASN1_F_ASN1_ITEM_VERIFY				 197
#define ASN1_F_ASN1_MBSTRING_NCOPY			 122
@@ -1291,6 +1292,7 @@ void ERR_load_ASN1_strings(void);
#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH			 106
#define ASN1_R_BUFFER_TOO_SMALL				 107
#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER		 108
#define ASN1_R_CONTEXT_NOT_INITIALISED			 217
#define ASN1_R_DATA_IS_WRONG				 109
#define ASN1_R_DECODE_ERROR				 110
#define ASN1_R_DECODING_ERROR				 111
+3 −1
Original line number Diff line number Diff line
/* crypto/asn1/asn1_err.c */
/* ====================================================================
 * Copyright (c) 1999-2009 The OpenSSL Project.  All rights reserved.
 * Copyright (c) 1999-2010 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
@@ -107,6 +107,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
{ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_FP),	"ASN1_item_i2d_fp"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_PACK),	"ASN1_item_pack"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN),	"ASN1_item_sign"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN_CTX),	"ASN1_item_sign_ctx"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_UNPACK),	"ASN1_item_unpack"},
{ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY),	"ASN1_item_verify"},
{ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY),	"ASN1_mbstring_ncopy"},
@@ -208,6 +209,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
{ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH),"boolean is wrong length"},
{ERR_REASON(ASN1_R_BUFFER_TOO_SMALL)     ,"buffer too small"},
{ERR_REASON(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER),"cipher has no object identifier"},
{ERR_REASON(ASN1_R_CONTEXT_NOT_INITIALISED),"context not initialised"},
{ERR_REASON(ASN1_R_DATA_IS_WRONG)        ,"data is wrong"},
{ERR_REASON(ASN1_R_DECODE_ERROR)         ,"decode error"},
{ERR_REASON(ASN1_R_DECODING_ERROR)       ,"decoding error"},
+3 −0
Original line number Diff line number Diff line
@@ -119,6 +119,9 @@ struct evp_pkey_asn1_method_st
	int (*item_verify)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
				X509_ALGOR *a, ASN1_BIT_STRING *sig,
				EVP_PKEY *pkey);
	int (*item_sign)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
				X509_ALGOR *alg1, X509_ALGOR *alg2, 
				ASN1_BIT_STRING *sig);

	} /* EVP_PKEY_ASN1_METHOD */;