1/* 2 * The contents of this file are subject to the Mozilla Public 3 * License Version 1.1 (the "License"); you may not use this file 4 * except in compliance with the License. You may obtain a copy of 5 * the License at http://www.mozilla.org/MPL/ 6 * 7 * Software distributed under the License is distributed on an "AS 8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 9 * implied. See the License for the specific language governing 10 * rights and limitations under the License. 11 * 12 * The Original Code is the Netscape security libraries. 13 * 14 * The Initial Developer of the Original Code is Netscape 15 * Communications Corporation. Portions created by Netscape are 16 * Copyright (C) 1994-2000 Netscape Communications Corporation. All 17 * Rights Reserved. 18 * 19 * Contributor(s): 20 * 21 * Alternatively, the contents of this file may be used under the 22 * terms of the GNU General Public License Version 2 or later (the 23 * "GPL"), in which case the provisions of the GPL are applicable 24 * instead of those above. If you wish to allow use of your 25 * version of this file only under the terms of the GPL and not to 26 * allow others to use your version of this file under the MPL, 27 * indicate your decision by deleting the provisions above and 28 * replace them with the notice and other provisions required by 29 * the GPL. If you do not delete the provisions above, a recipient 30 * may use your version of this file under either the MPL or the 31 * GPL. 32 */ 33 34/* 35 * CMS digestedData methods. 36 */ 37 38#include <Security/SecCmsDigestedData.h> 39 40#include <Security/SecCmsContentInfo.h> 41#include <Security/SecCmsDigestContext.h> 42 43#include "cmslocal.h" 44 45#include "secitem.h" 46#include "secoid.h" 47#include <security_asn1/secasn1.h> 48#include <security_asn1/secerr.h> 49 50/* 51 * SecCmsDigestedDataCreate - create a digestedData object (presumably for encoding) 52 * 53 * version will be set by SecCmsDigestedDataEncodeBeforeStart 54 * digestAlg is passed as parameter 55 * contentInfo must be filled by the user 56 * digest will be calculated while encoding 57 */ 58SecCmsDigestedDataRef 59SecCmsDigestedDataCreate(SecCmsMessageRef cmsg, SECAlgorithmID *digestalg) 60{ 61 void *mark; 62 SecCmsDigestedDataRef digd; 63 PLArenaPool *poolp; 64 65 poolp = cmsg->poolp; 66 67 mark = PORT_ArenaMark(poolp); 68 69 digd = (SecCmsDigestedDataRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsDigestedData)); 70 if (digd == NULL) 71 goto loser; 72 73 digd->cmsg = cmsg; 74 75 if (SECOID_CopyAlgorithmID (poolp, &(digd->digestAlg), digestalg) != SECSuccess) 76 goto loser; 77 78 PORT_ArenaUnmark(poolp, mark); 79 return digd; 80 81loser: 82 PORT_ArenaRelease(poolp, mark); 83 return NULL; 84} 85 86/* 87 * SecCmsDigestedDataDestroy - destroy a digestedData object 88 */ 89void 90SecCmsDigestedDataDestroy(SecCmsDigestedDataRef digd) 91{ 92 /* everything's in a pool, so don't worry about the storage */ 93 SecCmsContentInfoDestroy(&(digd->contentInfo)); 94 return; 95} 96 97/* 98 * SecCmsDigestedDataGetContentInfo - return pointer to digestedData object's contentInfo 99 */ 100SecCmsContentInfoRef 101SecCmsDigestedDataGetContentInfo(SecCmsDigestedDataRef digd) 102{ 103 return &(digd->contentInfo); 104} 105 106/* 107 * SecCmsDigestedDataEncodeBeforeStart - do all the necessary things to a DigestedData 108 * before encoding begins. 109 * 110 * In particular: 111 * - set the right version number. The contentInfo's content type must be set up already. 112 */ 113OSStatus 114SecCmsDigestedDataEncodeBeforeStart(SecCmsDigestedDataRef digd) 115{ 116 unsigned long version; 117 CSSM_DATA_PTR dummy; 118 119 version = SEC_CMS_DIGESTED_DATA_VERSION_DATA; 120 if (SecCmsContentInfoGetContentTypeTag(&(digd->contentInfo)) != SEC_OID_PKCS7_DATA) 121 version = SEC_CMS_DIGESTED_DATA_VERSION_ENCAP; 122 123 dummy = SEC_ASN1EncodeInteger(digd->cmsg->poolp, &(digd->version), version); 124 return (dummy == NULL) ? SECFailure : SECSuccess; 125} 126 127/* 128 * SecCmsDigestedDataEncodeBeforeData - do all the necessary things to a DigestedData 129 * before the encapsulated data is passed through the encoder. 130 * 131 * In detail: 132 * - set up the digests if necessary 133 */ 134OSStatus 135SecCmsDigestedDataEncodeBeforeData(SecCmsDigestedDataRef digd) 136{ 137 /* set up the digests */ 138 if (digd->digestAlg.algorithm.Length != 0 && digd->digest.Length == 0) { 139 /* if digest is already there, do nothing */ 140 digd->contentInfo.digcx = SecCmsDigestContextStartSingle(&(digd->digestAlg)); 141 if (digd->contentInfo.digcx == NULL) 142 return SECFailure; 143 } 144 return SECSuccess; 145} 146 147/* 148 * SecCmsDigestedDataEncodeAfterData - do all the necessary things to a DigestedData 149 * after all the encapsulated data was passed through the encoder. 150 * 151 * In detail: 152 * - finish the digests 153 */ 154OSStatus 155SecCmsDigestedDataEncodeAfterData(SecCmsDigestedDataRef digd) 156{ 157 OSStatus rv = SECSuccess; 158 /* did we have digest calculation going on? */ 159 if (digd->contentInfo.digcx) { 160 rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, 161 (SecArenaPoolRef)digd->cmsg->poolp, &(digd->digest)); 162 /* error has been set by SecCmsDigestContextFinishSingle */ 163 digd->contentInfo.digcx = NULL; 164 } 165 166 return rv; 167} 168 169/* 170 * SecCmsDigestedDataDecodeBeforeData - do all the necessary things to a DigestedData 171 * before the encapsulated data is passed through the encoder. 172 * 173 * In detail: 174 * - set up the digests if necessary 175 */ 176OSStatus 177SecCmsDigestedDataDecodeBeforeData(SecCmsDigestedDataRef digd) 178{ 179 /* is there a digest algorithm yet? */ 180 if (digd->digestAlg.algorithm.Length == 0) 181 return SECFailure; 182 183 digd->contentInfo.digcx = SecCmsDigestContextStartSingle(&(digd->digestAlg)); 184 if (digd->contentInfo.digcx == NULL) 185 return SECFailure; 186 187 return SECSuccess; 188} 189 190/* 191 * SecCmsDigestedDataDecodeAfterData - do all the necessary things to a DigestedData 192 * after all the encapsulated data was passed through the encoder. 193 * 194 * In detail: 195 * - finish the digests 196 */ 197OSStatus 198SecCmsDigestedDataDecodeAfterData(SecCmsDigestedDataRef digd) 199{ 200 OSStatus rv = SECSuccess; 201 /* did we have digest calculation going on? */ 202 if (digd->contentInfo.digcx) { 203 rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, 204 (SecArenaPoolRef)digd->cmsg->poolp, &(digd->cdigest)); 205 /* error has been set by SecCmsDigestContextFinishSingle */ 206 digd->contentInfo.digcx = NULL; 207 } 208 209 return rv; 210} 211 212/* 213 * SecCmsDigestedDataDecodeAfterEnd - finalize a digestedData. 214 * 215 * In detail: 216 * - check the digests for equality 217 */ 218OSStatus 219SecCmsDigestedDataDecodeAfterEnd(SecCmsDigestedDataRef digd) 220{ 221 /* did we have digest calculation going on? */ 222 if (digd->cdigest.Length != 0) { 223 /* XXX comparision btw digest & cdigest */ 224 /* XXX set status */ 225 /* TODO!!!! */ 226 } 227 228 return SECSuccess; 229} 230