1/* 2 * Copyright (c) 2003,2005 Apple Computer, Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please 7 * obtain a copy of the License at http://www.apple.com/publicsource and 8 * read it before using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 15 * Please see the License for the specific language governing rights and 16 * limitations under the License. 17 */ 18 19/* 20 * pkcs12Utils.cpp - standalone copies of utility functions from libsecurity_pkcs12 21 */ 22 23#include "pkcs12Utils.h" 24#include <string.h> 25#include <Security/oidsalg.h> 26#include <security_asn1/nssUtils.h> 27 28/* CSSM_DATA --> uint32. Returns true if OK. */ 29bool p12DataToInt( 30 const CSSM_DATA &cdata, 31 uint32 &u) 32{ 33 if((cdata.Length == 0) || (cdata.Data == NULL)) { 34 /* default/not present */ 35 u = 0; 36 return true; 37 } 38 uint32 len = cdata.Length; 39 if(len > sizeof(uint32)) { 40 return false; 41 } 42 43 uint32 rtn = 0; 44 uint8 *cp = cdata.Data; 45 for(uint32 i=0; i<len; i++) { 46 rtn = (rtn << 8) | *cp++; 47 } 48 u = rtn; 49 return true; 50} 51 52/* 53 * OIDS for P12 and PKCS5 v1.5 (PBES1) encrypt and decrypt map to the following 54 * attributes. 55 */ 56typedef struct { 57 const CSSM_OID *oid; 58 CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES 59 CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE 60 CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 61 uint32 keySizeInBits; 62 uint32 blockSizeInBytes; // for IV, optional 63 CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. 64 CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. 65 PKCS_Which pkcs; // PW_PKCS12 (for this module) or PW_PKCS5_v1_5 66} PKCSOidInfo; 67 68static const PKCSOidInfo pkcsOidInfos[] = { 69 /* PKCS12 first, the ones this module uses */ 70 { 71 &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4, 72 CSSM_ALGID_RC4, 73 CSSM_ALGID_RC4, 74 CSSM_ALGID_SHA1, 75 128, 76 0, // RC4 is a stream cipher 77 CSSM_PADDING_NONE, 78 CSSM_ALGMODE_NONE, 79 PW_PKCS12 80 }, 81 { 82 &CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4, 83 CSSM_ALGID_RC4, 84 CSSM_ALGID_RC4, 85 CSSM_ALGID_SHA1, 86 40, 87 0, // RC4 is a stream cipher 88 CSSM_PADDING_NONE, 89 CSSM_ALGMODE_NONE, 90 PW_PKCS12 91 }, 92 { 93 &CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC, 94 CSSM_ALGID_3DES_3KEY, 95 CSSM_ALGID_3DES_3KEY_EDE, 96 CSSM_ALGID_SHA1, 97 64 * 3, 98 8, 99 CSSM_PADDING_PKCS7, 100 CSSM_ALGMODE_CBCPadIV8, 101 PW_PKCS12 102 }, 103 { 104 &CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC, 105 CSSM_ALGID_3DES_2KEY, 106 CSSM_ALGID_3DES_2KEY_EDE, 107 CSSM_ALGID_SHA1, 108 64 * 2, 109 8, 110 CSSM_PADDING_PKCS7, 111 CSSM_ALGMODE_CBCPadIV8, 112 PW_PKCS12 113 }, 114 { 115 &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC, 116 CSSM_ALGID_RC2, 117 CSSM_ALGID_RC2, 118 CSSM_ALGID_SHA1, 119 128, 120 8, 121 CSSM_PADDING_PKCS7, 122 CSSM_ALGMODE_CBCPadIV8, 123 PW_PKCS12 124 }, 125 { 126 &CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC, 127 CSSM_ALGID_RC2, 128 CSSM_ALGID_RC2, 129 CSSM_ALGID_SHA1, 130 40, 131 8, 132 CSSM_PADDING_PKCS7, 133 CSSM_ALGMODE_CBCPadIV8, 134 PW_PKCS12 135 }, 136 137 /* PKCS5 v1.5, used for SecImportExport module */ 138 { 139 &CSSMOID_PKCS5_pbeWithMD2AndDES, 140 CSSM_ALGID_DES, 141 CSSM_ALGID_DES, 142 CSSM_ALGID_MD2, 143 64, 144 8, 145 CSSM_PADDING_PKCS7, 146 CSSM_ALGMODE_CBCPadIV8, 147 PW_PKCS5_v1_5 148 }, 149 { 150 &CSSMOID_PKCS5_pbeWithMD2AndRC2, 151 CSSM_ALGID_RC2, 152 CSSM_ALGID_RC2, 153 CSSM_ALGID_MD2, 154 64, 155 8, 156 CSSM_PADDING_PKCS7, 157 CSSM_ALGMODE_CBCPadIV8, 158 PW_PKCS5_v1_5 159 }, 160 { 161 &CSSMOID_PKCS5_pbeWithMD5AndDES, 162 CSSM_ALGID_DES, 163 CSSM_ALGID_DES, 164 CSSM_ALGID_MD5, 165 64, 166 8, 167 CSSM_PADDING_PKCS7, 168 CSSM_ALGMODE_CBCPadIV8, 169 PW_PKCS5_v1_5 170 }, 171 { 172 &CSSMOID_PKCS5_pbeWithMD5AndRC2, 173 CSSM_ALGID_RC2, 174 CSSM_ALGID_RC2, 175 CSSM_ALGID_MD5, 176 64, 177 8, 178 CSSM_PADDING_PKCS7, 179 CSSM_ALGMODE_CBCPadIV8, 180 PW_PKCS5_v1_5 181 }, 182 { 183 &CSSMOID_PKCS5_pbeWithSHA1AndDES, 184 CSSM_ALGID_DES, 185 CSSM_ALGID_DES, 186 CSSM_ALGID_SHA1, 187 64, 188 8, 189 CSSM_PADDING_PKCS7, 190 CSSM_ALGMODE_CBCPadIV8, 191 PW_PKCS5_v1_5 192 }, 193 { 194 &CSSMOID_PKCS5_pbeWithSHA1AndRC2, 195 CSSM_ALGID_RC2, 196 CSSM_ALGID_RC2, 197 CSSM_ALGID_SHA1, 198 64, 199 8, 200 CSSM_PADDING_PKCS7, 201 CSSM_ALGMODE_CBCPadIV8, 202 PW_PKCS5_v1_5 203 }, 204 205 /* finally one for PKCS5 v2.0, which has its own means of 206 * cooking up all the parameters */ 207 { 208 &CSSMOID_PKCS5_PBES2, 209 CSSM_ALGID_NONE, 210 CSSM_ALGID_NONE, 211 CSSM_ALGID_NONE, 212 0, 0, 0, 0, 213 PW_PKCS5_v2 214 } 215}; 216 217#define NUM_PKCS_OID_INFOS (sizeof(pkcsOidInfos) / sizeof(pkcsOidInfos[1])) 218 219/* map an OID to the components */ 220/* returns false if OID not found */ 221 222/* 223 * NOTE: as of March 8 2004 this is also used by the SecImportExport 224 * module...not just PKCS12! 225 */ 226bool pkcsOidToParams( 227 const CSSM_OID *oid, 228 CSSM_ALGORITHMS &keyAlg, // e.g., CSSM_ALGID_DES 229 CSSM_ALGORITHMS &encrAlg, // e.g., CSSM_ALGID_3DES_3KEY_EDE 230 CSSM_ALGORITHMS &pbeHashAlg, // SHA1 or MD5 231 uint32 &keySizeInBits, 232 uint32 &blockSizeInBytes, // for IV, optional 233 CSSM_PADDING &padding, // CSSM_PADDING_PKCS7, etc. 234 CSSM_ENCRYPT_MODE &mode, // CSSM_ALGMODE_CBCPadIV8, etc. 235 PKCS_Which &pkcs) // PW_PKCS5_v1_5 or PW_PKCS12 236{ 237 const PKCSOidInfo *info = pkcsOidInfos; 238 pkcs = PW_None; 239 240 for(unsigned dex=0; dex<NUM_PKCS_OID_INFOS; dex++) { 241 if(nssCompareCssmData(oid, info->oid)) { 242 keyAlg = info->keyAlg; 243 encrAlg = info->encrAlg; 244 pbeHashAlg = info->pbeHashAlg; 245 keySizeInBits = info->keySizeInBits; 246 blockSizeInBytes = info->blockSizeInBytes; 247 padding = info->padding; 248 mode = info->mode; 249 pkcs = info->pkcs; 250 return true; 251 } 252 info++; 253 } 254 return false; 255} 256 257/* 258 * Enum to string mappper. 259 * Maybe DEBUG only. 260 */ 261/* 262 * Each type of attribute has a name/value pair in a table of these: 263 */ 264typedef struct { 265 unsigned value; 266 const char *name; 267} p12NameValuePair; 268 269/* declare one entry in a table of p12NameValuePair */ 270#define NVP(attr) {attr, #attr} 271 272/* the NULL entry which terminates all p12NameValuePair tables */ 273#define NVP_END {0, NULL} 274 275static const p12NameValuePair p7CITypeNames[] = 276{ 277 NVP(CT_None), 278 NVP(CT_Data), 279 NVP(CT_SignedData), 280 NVP(CT_EnvData), 281 NVP(CT_SignedEnvData), 282 NVP(CT_DigestData), 283 NVP(CT_EncryptedData), 284 NVP_END 285}; 286 287static const p12NameValuePair p12BagTypeNames[] = 288{ 289 NVP(BT_None), 290 NVP(BT_KeyBag), 291 NVP(BT_ShroudedKeyBag), 292 NVP(BT_CertBag), 293 NVP(BT_CrlBag), 294 NVP(BT_SecretBag), 295 NVP(BT_SafeContentsBag), 296 NVP_END 297}; 298 299static const char *typeToStr( 300 unsigned type, 301 const p12NameValuePair *table) 302{ 303 while(table->name) { 304 if(table->value == type) { 305 return table->name; 306 } 307 table++; 308 } 309 return "Unknown"; 310} 311 312const char *p12BagTypeStr( 313 NSS_P12_SB_Type type) 314{ 315 return typeToStr(type, p12BagTypeNames); 316} 317 318const char *p7ContentInfoTypeStr( 319 NSS_P7_CI_Type type) 320{ 321 return typeToStr(type, p7CITypeNames); 322} 323