1/* 2 * Copyright (c) 2003-2004,2011,2013-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * pkcs12Templates.cpp 25 */ 26 27#include "pkcs12Templates.h" 28#include "pkcs12Utils.h" 29#include <security_asn1/nssUtils.h> 30#include <Security/SecAsn1Templates.h> 31#include <Security/oidsattr.h> 32 33#pragma clang diagnostic push 34#pragma clang diagnostic ignored "-Wunused-const-variable" 35 36 37const SecAsn1Template NSS_P12_MacDataTemplate[] = { 38 { SEC_ASN1_SEQUENCE, 39 0, NULL, sizeof(NSS_P12_MacData) }, 40 { SEC_ASN1_INLINE, 41 offsetof(NSS_P12_MacData,mac), 42 NSS_P7_DigestInfoTemplate }, 43 { SEC_ASN1_OCTET_STRING, 44 offsetof(NSS_P12_MacData,macSalt) }, 45 /* iterations is unsigned - right? */ 46 { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, 47 offsetof(NSS_P12_MacData,iterations) }, 48 { 0, } 49}; 50 51const SecAsn1Template pointerToMacDataTemplate[] = { 52 { SEC_ASN1_POINTER, 0, NSS_P12_MacDataTemplate } 53}; 54 55/* raw PFX with unprocessed authSafe */ 56const SecAsn1Template NSS_P12_RawPFXTemplate[] = { 57 { SEC_ASN1_SEQUENCE, 58 0, NULL, sizeof(NSS_P12_RawPFX) }, 59 { SEC_ASN1_INTEGER, 60 offsetof(NSS_P12_RawPFX,version) }, 61 { SEC_ASN1_INLINE, 62 offsetof(NSS_P12_RawPFX, authSafe), 63 NSS_P7_RawContentInfoTemplate }, 64 { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL, 65 offsetof(NSS_P12_RawPFX, macData), 66 NSS_P12_MacDataTemplate }, 67 { 0, } 68}; 69 70/* PFX with decoded authSafe */ 71extern const SecAsn1Template NSS_P12_DecodedPFXTemplate[] = { 72 { SEC_ASN1_SEQUENCE, 73 0, NULL, sizeof(NSS_P12_DecodedPFX) }, 74 { SEC_ASN1_INTEGER, 75 offsetof(NSS_P12_DecodedPFX,version) }, 76 { SEC_ASN1_INLINE, 77 offsetof(NSS_P12_DecodedPFX, authSafe), 78 NSS_P7_DecodedContentInfoTemplate }, 79 { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL, 80 offsetof(NSS_P12_DecodedPFX, macData), 81 NSS_P12_MacDataTemplate }, 82 { 0, } 83}; 84 85/* AuthenticatedSafe */ 86const SecAsn1Template NSS_P12_AuthenticatedSafeTemplate[] = { 87 { SEC_ASN1_SEQUENCE_OF, 88 offsetof(NSS_P12_AuthenticatedSafe, info), 89 NSS_P7_DecodedContentInfoTemplate, 90 sizeof(NSS_P12_AuthenticatedSafe) } 91}; 92 93/* 94 * Individual SafeBag type-specific templates here when we write 'em 95 */ 96const SecAsn1Template NSS_P12_PtrToShroudedKeyBagTemplate[] = { 97 { SEC_ASN1_POINTER, 0, kSecAsn1EncryptedPrivateKeyInfoTemplate } 98}; 99 100/* 101 * CertBag via SEC_ASN1_DYNAMIC 102 */ 103static const SecAsn1Template * NSS_P12_CertBagChooser( 104 void *arg, // --> NSS_P12_CertBag 105 Boolean enc, 106 const char *buf, // on decode, tag byte 107 void *dest) // --> NSS_P12_CertBag.bagValue 108{ 109 NSS_P12_CertBag *bag = (NSS_P12_CertBag *)arg; 110 const SecAsn1Template *templ = NULL; 111 NSS_P12_CertBagType type = CT_Unknown; 112 CSSM_OID *oid = &bag->bagType; 113 114 if(nssCompareCssmData(oid, &CSSMOID_PKCS9_X509Certificate)) { 115 templ = kSecAsn1OctetStringTemplate; 116 type = CT_X509; 117 } 118 else if(nssCompareCssmData(oid, &CSSMOID_PKCS9_SdsiCertificate)) { 119 templ = kSecAsn1IA5StringTemplate; 120 type = CT_SDSI; 121 } 122 else { 123 /* punt */ 124 templ = kSecAsn1AnyTemplate; 125 } 126 if(!enc) { 127 bag->type = type; 128 } 129 return templ; 130} 131 132static const SecAsn1TemplateChooserPtr NSS_P12_CertBagChooserPtr = 133 NSS_P12_CertBagChooser; 134 135const SecAsn1Template NSS_P12_CertBagTemplate[] = { 136 { SEC_ASN1_SEQUENCE, 137 0, NULL, sizeof(NSS_P12_CertBag) }, 138 { SEC_ASN1_OBJECT_ID, 139 offsetof(NSS_P12_CertBag,bagType) }, 140 /* these come in with a tag of 0xA0, context/constructed, 141 * though I don't know why they are flagged as constructed */ 142 { SEC_ASN1_DYNAMIC | SEC_ASN1_CONTEXT_SPECIFIC | 143 SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | 0, 144 offsetof(NSS_P12_CertBag, certValue), 145 &NSS_P12_CertBagChooserPtr }, 146 { 0, } 147}; 148 149const SecAsn1Template NSS_P12_PtrToCertBagTemplate[] = { 150 { SEC_ASN1_POINTER, 0, NSS_P12_CertBagTemplate } 151}; 152 153/* 154 * CrlBag via SEC_ASN1_DYNAMIC 155 */ 156static const SecAsn1Template * NSS_P12_CrlBagChooser( 157 void *arg, // --> NSS_P12_CrlBag 158 Boolean enc, 159 const char *buf, // on decode, tag byte 160 void *dest) // --> NSS_P12_CertBag.bagValue 161{ 162 NSS_P12_CrlBag *bag = (NSS_P12_CrlBag *)arg; 163 const SecAsn1Template *templ = NULL; 164 NSS_P12_CrlBagType type = CRT_Unknown; 165 CSSM_OID *oid = &bag->bagType; 166 167 if(nssCompareCssmData(oid, &CSSMOID_PKCS9_X509Crl)) { 168 templ = kSecAsn1OctetStringTemplate; 169 type = CRT_X509; 170 } 171 else { 172 /* punt */ 173 templ = kSecAsn1AnyTemplate; 174 } 175 if(!enc) { 176 bag->type = type; 177 } 178 return templ; 179} 180 181static const SecAsn1TemplateChooserPtr NSS_P12_CrlBagChooserPtr = 182 NSS_P12_CrlBagChooser; 183 184const SecAsn1Template NSS_P12_CrlBagTemplate[] = { 185 { SEC_ASN1_SEQUENCE, 186 0, NULL, sizeof(NSS_P12_CrlBag) }, 187 { SEC_ASN1_OBJECT_ID, 188 offsetof(NSS_P12_CrlBag,bagType) }, 189 /* these come in with a tag of 0xA0, context/constructed, 190 * though I don't know why they are flagged as constructed */ 191 { SEC_ASN1_DYNAMIC | SEC_ASN1_CONTEXT_SPECIFIC | 192 SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | 0, 193 offsetof(NSS_P12_CrlBag, crlValue), 194 &NSS_P12_CrlBagChooserPtr }, 195 { 0, } 196}; 197 198const SecAsn1Template NSS_P12_PtrToCrlBagTemplate[] = { 199 { SEC_ASN1_POINTER, 0, NSS_P12_CrlBagTemplate } 200}; 201 202 203/* the stub templates for unimplemented BagTypes */ 204#define NSS_P12_PtrToKeyBagTemplate kSecAsn1PointerToAnyTemplate 205#define NSS_P12_PtrToSecretBagTemplate kSecAsn1PointerToAnyTemplate 206#define NSS_P12_PtrToSafeContentsBagTemplate kSecAsn1PointerToAnyTemplate 207 208 209/* 210 * SafeBag via SEC_ASN1_DYNAMIC 211 */ 212static const SecAsn1Template * NSS_P12_SafeBagChooser( 213 void *arg, // --> NSS_P12_SafeBag 214 Boolean enc, 215 const char *buf, // on decode, tag byte 216 void *dest) // --> NSS_P12_SafeBag.bagValue 217{ 218 NSS_P12_SafeBag *bag = (NSS_P12_SafeBag *)arg; 219 const SecAsn1Template *templ = NULL; 220 NSS_P12_SB_Type type = BT_None; 221 CSSM_OID *oid = &bag->bagId; 222 223 if(nssCompareCssmData(oid, &CSSMOID_PKCS12_keyBag)) { 224 templ = NSS_P12_PtrToKeyBagTemplate; 225 type = BT_KeyBag; 226 } 227 else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_shroudedKeyBag)) { 228 templ = NSS_P12_PtrToShroudedKeyBagTemplate; 229 type = BT_ShroudedKeyBag; 230 } 231 else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_certBag)) { 232 templ = NSS_P12_PtrToCertBagTemplate; 233 type = BT_CertBag; 234 } 235 else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_crlBag)) { 236 templ = NSS_P12_PtrToCrlBagTemplate; 237 type = BT_CrlBag; 238 } 239 else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_secretBag)) { 240 templ = NSS_P12_PtrToSecretBagTemplate; 241 type = BT_SecretBag; 242 } 243 else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_safeContentsBag)) { 244 templ = NSS_P12_PtrToSafeContentsBagTemplate; 245 type = BT_SafeContentsBag; 246 } 247 /* add more here when we implement them */ 248 else { 249 templ = kSecAsn1PointerToAnyTemplate; 250 } 251 if(!enc) { 252 bag->type = type; 253 } 254 return templ; 255} 256 257static const SecAsn1TemplateChooserPtr NSS_P12_SafeBagChooserPtr = 258 NSS_P12_SafeBagChooser; 259 260const SecAsn1Template NSS_P12_SafeBagTemplate[] = { 261 { SEC_ASN1_SEQUENCE, 262 0, NULL, sizeof(NSS_P12_SafeBag) }, 263 { SEC_ASN1_OBJECT_ID, 264 offsetof(NSS_P12_SafeBag,bagId) }, 265 { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 266 SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, 267 offsetof(NSS_P12_SafeBag,bagValue), 268 &NSS_P12_SafeBagChooserPtr }, 269 { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF, 270 offsetof(NSS_P12_SafeBag,bagAttrs), 271 kSecAsn1AttributeTemplate }, 272 { 0 } 273}; 274 275const SecAsn1Template NSS_P12_SafeContentsTemplate[] = { 276 { SEC_ASN1_SEQUENCE_OF, 277 offsetof(NSS_P12_SafeContents, bags), 278 NSS_P12_SafeBagTemplate, 279 sizeof(NSS_P12_SafeContents) } 280}; 281 282const SecAsn1Template NSS_P12_PBE_ParamsTemplate[] = { 283 { SEC_ASN1_SEQUENCE, 284 0, NULL, sizeof(NSS_P12_PBE_Params) }, 285 { SEC_ASN1_OCTET_STRING, 286 offsetof(NSS_P12_PBE_Params,salt) }, 287 /* iterations is unsigned - right? */ 288 { SEC_ASN1_INTEGER, 289 offsetof(NSS_P12_PBE_Params,iterations) }, 290 { 0 } 291}; 292 293#pragma clang diagnostic pop 294