Back to index

lightning-sunbird  0.9+nobinonly
secdig.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 /* $Id: secdig.c,v 1.5.28.2 2006/08/31 03:57:56 nelson%bolyard.com Exp $ */
00037 #include "secdig.h"
00038 
00039 #include "secoid.h"
00040 #include "secasn1.h" 
00041 #include "secerr.h"
00042 
00043 /*
00044  * XXX OLD Template.  Once all uses have been switched over to new one,
00045  * remove this.
00046  */
00047 DERTemplate SGNDigestInfoTemplate[] = {
00048     { DER_SEQUENCE,
00049          0, NULL, sizeof(SGNDigestInfo) },
00050     { DER_INLINE,
00051          offsetof(SGNDigestInfo,digestAlgorithm),
00052          SECAlgorithmIDTemplate, },
00053     { DER_OCTET_STRING,
00054          offsetof(SGNDigestInfo,digest), },
00055     { 0, }
00056 };
00057 
00058 /* XXX See comment below about SGN_DecodeDigestInfo -- keep this static! */
00059 /* XXX Changed from static -- need to change name? */
00060 const SEC_ASN1Template sgn_DigestInfoTemplate[] = {
00061     { SEC_ASN1_SEQUENCE,
00062          0, NULL, sizeof(SGNDigestInfo) },
00063     { SEC_ASN1_INLINE,
00064          offsetof(SGNDigestInfo,digestAlgorithm),
00065          SECOID_AlgorithmIDTemplate },
00066     { SEC_ASN1_OCTET_STRING,
00067          offsetof(SGNDigestInfo,digest) },
00068     { 0 }
00069 };
00070 
00071 SEC_ASN1_CHOOSER_IMPLEMENT(sgn_DigestInfoTemplate)
00072 
00073 /*
00074  * XXX Want to have a SGN_DecodeDigestInfo, like:
00075  *     SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
00076  * that creates a pool and allocates from it and decodes didata into
00077  * the newly allocated DigestInfo structure.  Then fix secvfy.c (it
00078  * will no longer need an arena itself) to call this and then call
00079  * DestroyDigestInfo when it is done, then can remove the old template
00080  * above and keep our new template static and "hidden".
00081  */
00082 
00083 /*
00084  * XXX It might be nice to combine the following two functions (create
00085  * and encode).  I think that is all anybody ever wants to do anyway.
00086  */
00087 
00088 SECItem *
00089 SGN_EncodeDigestInfo(PRArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo)
00090 {
00091     return SEC_ASN1EncodeItem (poolp, dest, diginfo, sgn_DigestInfoTemplate);
00092 }
00093 
00094 SGNDigestInfo *
00095 SGN_CreateDigestInfo(SECOidTag algorithm, unsigned char *sig, unsigned len)
00096 {
00097     SGNDigestInfo *di;
00098     SECStatus rv;
00099     PRArenaPool *arena;
00100     SECItem *null_param;
00101     SECItem dummy_value;
00102 
00103     switch (algorithm) {
00104       case SEC_OID_MD2:
00105       case SEC_OID_MD5:
00106       case SEC_OID_SHA1:
00107       case SEC_OID_SHA256:
00108       case SEC_OID_SHA384:
00109       case SEC_OID_SHA512:
00110        break;
00111       default:
00112        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
00113        return NULL;
00114     }
00115 
00116     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00117     if (arena == NULL) {
00118        return NULL;
00119     }
00120 
00121     di = (SGNDigestInfo *) PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
00122     if (di == NULL) {
00123        PORT_FreeArena(arena, PR_FALSE);
00124        return NULL;
00125     }
00126 
00127     di->arena = arena;
00128 
00129     /*
00130      * PKCS #1 specifies that the AlgorithmID must have a NULL parameter
00131      * (as opposed to no parameter at all).
00132      */
00133     dummy_value.data = NULL;
00134     dummy_value.len = 0;
00135     null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
00136     if (null_param == NULL) {
00137        goto loser;
00138     }
00139 
00140     rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
00141                             null_param);
00142 
00143     SECITEM_FreeItem(null_param, PR_TRUE);
00144 
00145     if (rv != SECSuccess) {
00146        goto loser;
00147     }
00148 
00149     di->digest.data = (unsigned char *) PORT_ArenaAlloc(arena, len);
00150     if (di->digest.data == NULL) {
00151        goto loser;
00152     }
00153 
00154     di->digest.len = len;
00155     PORT_Memcpy(di->digest.data, sig, len);
00156     return di;
00157 
00158   loser:
00159     SGN_DestroyDigestInfo(di);
00160     return NULL;
00161 }
00162 
00163 SGNDigestInfo *
00164 SGN_DecodeDigestInfo(SECItem *didata)
00165 {
00166     PRArenaPool *arena;
00167     SGNDigestInfo *di;
00168     SECStatus rv = SECFailure;
00169     SECItem      diCopy   = {siBuffer, NULL, 0};
00170 
00171     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
00172     if(arena == NULL)
00173        return NULL;
00174 
00175     rv = SECITEM_CopyItem(arena, &diCopy, didata);
00176     if (rv != SECSuccess) {
00177        PORT_FreeArena(arena, PR_FALSE);
00178        return NULL;
00179     }
00180 
00181     di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
00182     if (di != NULL) {
00183        di->arena = arena;
00184        rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
00185     }
00186        
00187     if ((di == NULL) || (rv != SECSuccess)) {
00188        PORT_FreeArena(arena, PR_FALSE);
00189        di = NULL;
00190     }
00191 
00192     return di;
00193 }
00194 
00195 void
00196 SGN_DestroyDigestInfo(SGNDigestInfo *di)
00197 {
00198     if (di && di->arena) {
00199        PORT_FreeArena(di->arena, PR_FALSE);
00200     }
00201 
00202     return;
00203 }
00204 
00205 SECStatus 
00206 SGN_CopyDigestInfo(PRArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
00207 {
00208     SECStatus rv;
00209     void *mark;
00210 
00211     if((poolp == NULL) || (a == NULL) || (b == NULL))
00212        return SECFailure;
00213 
00214     mark = PORT_ArenaMark(poolp);
00215     a->arena = poolp;
00216     rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm, 
00217        &b->digestAlgorithm);
00218     if (rv == SECSuccess)
00219        rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);
00220 
00221     if (rv != SECSuccess) {
00222        PORT_ArenaRelease(poolp, mark);
00223     } else {
00224        PORT_ArenaUnmark(poolp, mark);
00225     }
00226 
00227     return rv;
00228 }
00229 
00230 SECComparison
00231 SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
00232 {
00233     SECComparison rv;
00234 
00235     /* Check signature algorithm's */
00236     rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
00237     if (rv) return rv;
00238 
00239     /* Compare signature block length's */
00240     rv = SECITEM_CompareItem(&a->digest, &b->digest);
00241     return rv;
00242 }