void p12GenSalt( CSSM_DATA &salt, SecNssCoder &coder) { DevRandomGenerator rng; coder.allocItem(salt, P12_SALT_LEN); rng.random(salt.Data, P12_SALT_LEN); }
/* * Generate random label string to allow associating an imported private * key with a cert. */ void p12GenLabel( CSSM_DATA &label, SecNssCoder &coder) { /* first a random uint32 */ uint8 d[4]; DevRandomGenerator rng; rng.random(d, 4); CSSM_DATA cd = {4, d}; uint32 i; p12DataToInt(cd, i); /* sprintf that into a real string */ coder.allocItem(label, 9); memset(label.Data, 0, 9); sprintf((char *)label.Data, "%08X", (unsigned)i); }
OSStatus impExpWrappedKeyOpenSslExport( SecKeyRef secKey, SecItemImportExportFlags flags, const SecKeyImportExportParameters *keyParams, // optional CFMutableDataRef outData, // output appended here const char **pemHeader, // RETURNED CFArrayRef *pemParamLines) // RETURNED { DevRandomGenerator rng; SecNssCoder coder; CSSM_CSP_HANDLE cspHand = 0; OSStatus ortn; bool releaseCspHand = false; CFMutableArrayRef paramLines; CFStringRef cfStr; char dekStr[100]; char ivStr[3]; if(keyParams == NULL) { return errSecParam; } /* we need a CSPDL handle - try to get it from the key */ ortn = SecKeyGetCSPHandle(secKey, &cspHand); if(ortn) { cspHand = cuCspStartup(CSSM_FALSE); if(cspHand == 0) { return CSSMERR_CSSM_ADDIN_LOAD_FAILED; } releaseCspHand = true; } /* subsequent errors to errOut: */ /* 8 bytes of random IV/salt */ uint8 saltIv[8]; CSSM_DATA saltIvData = { 8, saltIv} ; rng.random(saltIv, 8); /* derive wrapping key */ CSSM_KEY wrappingKey; wrappingKey.KeyData.Data = NULL; wrappingKey.KeyData.Length = 0; ortn = deriveKeyOpensslWrap(keyParams, cspHand, VP_Export, OPENSSL_WRAP_PBE_ALG, OPENSSL_WRAP_KEY_ALG, OPENSSL_WRAP_KEY_SIZE, saltIvData, // IV == salt for this wrapping alg &wrappingKey); if(ortn) { goto errOut; } /* wrap the outgoing key */ CSSM_KEY wrappedKey; memset(&wrappedKey, 0, sizeof(CSSM_KEY)); ortn = impExpExportKeyCommon(cspHand, secKey, &wrappingKey, &wrappedKey, OPENSSL_WRAP_ENCR_ALG, OPENSSL_WRAP_ENCR_MODE, OPENSSL_WRAP_ENCR_PAD, CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL, CSSM_ATTRIBUTE_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, NULL, &saltIvData); if(ortn) { goto errOut; } /* * That wrapped key's KeyData is our output */ CFDataAppendBytes(outData, wrappedKey.KeyData.Data, wrappedKey.KeyData.Length); /* PEM header depends on key algorithm */ switch(wrappedKey.KeyHeader.AlgorithmId) { case CSSM_ALGID_RSA: *pemHeader = PEM_STRING_RSA; break; case CSSM_ALGID_DH: *pemHeader = PEM_STRING_DH_PRIVATE; break; case CSSM_ALGID_DSA: *pemHeader = PEM_STRING_DSA; break; case CSSM_ALGID_ECDSA: *pemHeader = PEM_STRING_ECDSA_PRIVATE; break; default: SecImpExpDbg("impExpWrappedKeyOpenSslExport unknown private key alg " "%lu", (unsigned long)wrappedKey.KeyHeader.AlgorithmId); /* punt though I think something is seriously hosed */ *pemHeader = "Private Key"; } CSSM_FreeKey(cspHand, NULL, &wrappedKey, CSSM_FALSE); /* * Last thing: set up outgoing PEM parameter lines */ assert(pemParamLines != NULL); paramLines = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); cfStr = CFStringCreateWithCString(NULL, "Proc-Type: 4,ENCRYPTED", kCFStringEncodingASCII); CFArrayAppendValue(paramLines, cfStr); CFRelease(cfStr); // owned by array now */ strcpy(dekStr, "DEK-Info: DES-EDE3-CBC,"); /* next goes the IV */ for(unsigned dex=0; dex<8; dex++) { sprintf(ivStr, "%02X", saltIv[dex]); strcat(dekStr, ivStr); } cfStr = CFStringCreateWithCString(NULL, dekStr, kCFStringEncodingASCII); CFArrayAppendValue(paramLines, cfStr); CFRelease(cfStr); // owned by array now */ /* and an empty line */ cfStr = CFStringCreateWithCString(NULL, "", kCFStringEncodingASCII); CFArrayAppendValue(paramLines, cfStr); CFRelease(cfStr); // owned by array now */ *pemParamLines = paramLines; errOut: if(wrappingKey.KeyData.Data != NULL) { CSSM_FreeKey(cspHand, NULL, &wrappingKey, CSSM_FALSE); } return ortn; }