gecko-dev/security/nss/lib/util/secdig.c

231 строка
6.0 KiB
C

/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: secdig.c,v 1.1 2000/03/31 19:39:35 relyea%netscape.com Exp $
*/
#include "secdig.h"
#include "secoid.h"
#include "secasn1.h"
#include "secerr.h"
/*
* XXX OLD Template. Once all uses have been switched over to new one,
* remove this.
*/
DERTemplate SGNDigestInfoTemplate[] = {
{ DER_SEQUENCE,
0, NULL, sizeof(SGNDigestInfo) },
{ DER_INLINE,
offsetof(SGNDigestInfo,digestAlgorithm),
SECAlgorithmIDTemplate, },
{ DER_OCTET_STRING,
offsetof(SGNDigestInfo,digest), },
{ 0, }
};
/* XXX See comment below about SGN_DecodeDigestInfo -- keep this static! */
/* XXX Changed from static -- need to change name? */
const SEC_ASN1Template sgn_DigestInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(SGNDigestInfo) },
{ SEC_ASN1_INLINE,
offsetof(SGNDigestInfo,digestAlgorithm),
SECOID_AlgorithmIDTemplate },
{ SEC_ASN1_OCTET_STRING,
offsetof(SGNDigestInfo,digest) },
{ 0 }
};
/*
* XXX Want to have a SGN_DecodeDigestInfo, like:
* SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
* that creates a pool and allocates from it and decodes didata into
* the newly allocated DigestInfo structure. Then fix secvfy.c (it
* will no longer need an arena itself) to call this and then call
* DestroyDigestInfo when it is done, then can remove the old template
* above and keep our new template static and "hidden".
*/
/*
* XXX It might be nice to combine the following two functions (create
* and encode). I think that is all anybody ever wants to do anyway.
*/
SECItem *
SGN_EncodeDigestInfo(PRArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo)
{
return SEC_ASN1EncodeItem (poolp, dest, diginfo, sgn_DigestInfoTemplate);
}
SGNDigestInfo *
SGN_CreateDigestInfo(SECOidTag algorithm, unsigned char *sig, unsigned len)
{
SGNDigestInfo *di;
SECStatus rv;
PRArenaPool *arena;
SECItem *null_param;
SECItem dummy_value;
switch (algorithm) {
case SEC_OID_MD2:
case SEC_OID_MD5:
case SEC_OID_SHA1:
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
return NULL;
}
di = (SGNDigestInfo *) PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
if (di == NULL) {
PORT_FreeArena(arena, PR_FALSE);
return NULL;
}
di->arena = arena;
/*
* PKCS #1 specifies that the AlgorithmID must have a NULL parameter
* (as opposed to no parameter at all).
*/
dummy_value.data = NULL;
dummy_value.len = 0;
null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
if (null_param == NULL) {
goto loser;
}
rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
null_param);
SECITEM_FreeItem(null_param, PR_TRUE);
if (rv != SECSuccess) {
goto loser;
}
di->digest.data = (unsigned char *) PORT_ArenaAlloc(arena, len);
if (di->digest.data == NULL) {
goto loser;
}
di->digest.len = len;
PORT_Memcpy(di->digest.data, sig, len);
return di;
loser:
SGN_DestroyDigestInfo(di);
return NULL;
}
SGNDigestInfo *
SGN_DecodeDigestInfo(SECItem *didata)
{
PRArenaPool *arena;
SGNDigestInfo *di;
SECStatus rv = SECFailure;
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if(arena == NULL)
return NULL;
di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
if(di != NULL)
{
di->arena = arena;
rv = SEC_ASN1DecodeItem(arena, di, sgn_DigestInfoTemplate, didata);
}
if((di == NULL) || (rv != SECSuccess))
{
PORT_FreeArena(arena, PR_TRUE);
di = NULL;
}
return di;
}
void
SGN_DestroyDigestInfo(SGNDigestInfo *di)
{
if (di && di->arena) {
PORT_FreeArena(di->arena, PR_FALSE);
}
return;
}
SECStatus
SGN_CopyDigestInfo(PRArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
{
SECStatus rv;
void *mark;
if((poolp == NULL) || (a == NULL) || (b == NULL))
return SECFailure;
mark = PORT_ArenaMark(poolp);
a->arena = poolp;
rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm,
&b->digestAlgorithm);
if (rv == SECSuccess)
rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);
if (rv != SECSuccess) {
PORT_ArenaRelease(poolp, mark);
} else {
PORT_ArenaUnmark(poolp, mark);
}
return rv;
}
SECComparison
SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
{
SECComparison rv;
/* Check signature algorithm's */
rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
if (rv) return rv;
/* Compare signature block length's */
rv = SECITEM_CompareItem(&a->digest, &b->digest);
return rv;
}