static CF_RETURNS_RETAINED CFDictionaryRef SecKeyGenerateAttributeDictionaryFor(SecKeyRef key, CFTypeRef keyType, CFDataRef privateBlob) { CFAllocatorRef allocator = CFGetAllocator(key); DICT_DECLARE(25); CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL; CFDictionaryRef dict = NULL; size_t sizeValue = SecKeyGetSize(key, kSecKeyKeySizeInBits); CFNumberRef sizeInBits = CFNumberCreate(allocator, kCFNumberLongType, &sizeValue); /* encode the public key. */ require_noerr(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut); require(pubKeyBlob, errOut); /* Calculate the digest of the public key. */ require(pubKeyDigest = SecSHA1DigestCreate(allocator, CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)), errOut); DICT_ADDPAIR(kSecClass, kSecClassKey); DICT_ADDPAIR(kSecAttrKeyClass, privateBlob ? kSecAttrKeyClassPrivate : kSecAttrKeyClassPublic); DICT_ADDPAIR(kSecAttrApplicationLabel, pubKeyDigest); DICT_ADDPAIR(kSecAttrIsPermanent, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrIsPrivate, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrIsModifiable, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrKeyType, keyType); DICT_ADDPAIR(kSecAttrKeySizeInBits, sizeInBits); DICT_ADDPAIR(kSecAttrEffectiveKeySize, sizeInBits); DICT_ADDPAIR(kSecAttrIsSensitive, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrWasAlwaysSensitive, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrIsExtractable, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrWasNeverExtractable, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanEncrypt, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanDecrypt, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrCanDerive, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrCanSign, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrCanVerify, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanSignRecover, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanVerifyRecover, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanWrap, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanUnwrap, kCFBooleanTrue); DICT_ADDPAIR(kSecValueData, privateBlob ? privateBlob : pubKeyBlob); dict = DICT_CREATE(allocator); errOut: // @@@ Zero out key material. CFReleaseSafe(pubKeyDigest); CFReleaseSafe(pubKeyBlob); CFReleaseSafe(sizeInBits); return dict; }
/* Test basic add delete update copy matching stuff. */ static void tests(SecKeyDescriptor *descriptor) { const uint8_t *keyData = (const uint8_t *)"abc"; CFIndex keyDataLength = 3; SecKeyEncoding encoding = kSecKeyEncodingRaw; ok(customKey = SecKeyCreate(kCFAllocatorDefault, descriptor, keyData, keyDataLength, encoding), "create custom key"); is(customKey, initedCustomKey, "CustomKeyInit got the right key"); SecPadding padding = kSecPaddingPKCS1; const uint8_t *src = (const uint8_t *)"defgh"; size_t srcLen = 5; uint8_t dst[5]; size_t dstLen = 5; ok_status(SecKeyDecrypt(customKey, padding, src, srcLen, dst, &dstLen), "SecKeyDecrypt"); ok_status(SecKeyEncrypt(customKey, padding, src, srcLen, dst, &dstLen), "SecKeyEncrypt"); ok_status(SecKeyRawSign(customKey, padding, src, srcLen, dst, &dstLen), "SecKeyRawSign"); ok_status(SecKeyRawVerify(customKey, padding, src, srcLen, dst, dstLen), "SecKeyRawVerify"); is(SecKeyGetSize(customKey, kSecKeyKeySizeInBits), (size_t)5*8, "SecKeyGetSize"); CFDictionaryRef attrDict = NULL; ok(attrDict = SecKeyCopyAttributeDictionary(customKey), "SecKeyCopyAttributeDictionary"); CFReleaseNull(attrDict); CFDataRef pubdata = NULL; ok(SecKeyCopyPublicBytes(customKey, &pubdata) != 0, "SecKeyCopyPublicBytes"); CFReleaseNull(pubdata); CFDataRef wrapped; wrapped = _SecKeyCopyWrapKey(customKey, kSecKeyWrapPublicKeyPGP, pubdata, NULL, NULL, NULL); ok(wrapped == NULL, "_SecKeyCopyWrapKey"); CFReleaseNull(wrapped); wrapped = _SecKeyCopyUnwrapKey(customKey, kSecKeyWrapPublicKeyPGP, pubdata, NULL, NULL, NULL); ok(wrapped == NULL, "_SecKeyCopyUnwrapKey"); CFReleaseNull(wrapped); //ok(SecKeyGeneratePair(customKey, ), "SecKeyGeneratePair"); ok(SecKeyGetTypeID() != 0, "SecKeyGetTypeID works"); if (customKey) { CFRelease(customKey); customKey = NULL; } }
OSStatus SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, SecPublicKeyRef publickey, SecSymmetricKeyRef bulkkey, SecAsn1Item * encKey) { OSStatus rv; size_t data_len; //KeyType keyType; void *mark = NULL; mark = PORT_ArenaMark(poolp); if (!mark) goto loser; #if 0 /* sanity check */ keyType = SECKEY_GetPublicKeyType(publickey); PORT_Assert(keyType == rsaKey); if (keyType != rsaKey) { goto loser; } #endif /* allocate memory for the encrypted key */ #if USE_CDSA_CRYPTO rv = SecKeyGetStrengthInBits(publickey, NULL, &data_len); if (rv) goto loser; // Convert length to bytes; data_len >>= 2; #else data_len = SecKeyGetSize(publickey, kSecKeyEncryptedDataSize); #endif encKey->Data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len); encKey->Length = data_len; if (encKey->Data == NULL) goto loser; /* encrypt the key now */ rv = WRAP_PubWrapSymKey(publickey, bulkkey, encKey); if (rv != SECSuccess) goto loser; PORT_ArenaUnmark(poolp, mark); return SECSuccess; loser: if (mark) { PORT_ArenaRelease(poolp, mark); } return SECFailure; }
static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) { uint8_t dataToDigest[256] = {0,}; size_t dataToDigestLen = sizeof(dataToDigest); size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize); uint8_t sig[sigLen]; DERItem oid; oid.length = algId->algorithm.Length; oid.data = algId->algorithm.Data; /* Get the oid in decimal for display purposes. */ CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid); char oidBuf[40]; CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8); CFRelease(oidStr); SKIP: { OSStatus status; /* Time to sign. */ ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen, sig, &sigLen), "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8); skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess); /* Verify the signature we just made. */ ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, sig, sigLen), "digest and verify"); /* Invalidate the signature. */ sig[0] ^= 0xff; is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, sig, sigLen), errSSLCrypto, "digest and verify bad sig"); sig[0] ^= 0xff; dataToDigest[0] ^= 0xff; is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, sig, sigLen), errSSLCrypto, "digest and verify bad digest"); } }
static void testkeygen2(size_t keySizeInBits) { SecKeyRef pubKey = NULL, privKey = NULL; size_t keySizeInBytes = (keySizeInBits + 7) / 8; CFNumberRef kzib; int32_t keysz32 = (int32_t)keySizeInBits; CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); CFReleaseNull(ourUUID); CFReleaseNull(uuidString); CFStringAppend(publicName, CFSTR("-Public-41")); CFStringAppend(privateName, CFSTR("-Private-41")); CFMutableDictionaryRef pubd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecAttrLabel, publicName, NULL); CFMutableDictionaryRef privd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecAttrLabel, privateName, NULL); kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrKeyType, kSecAttrKeyTypeEC, kSecAttrKeySizeInBits, kzib, kSecAttrIsPermanent, kCFBooleanTrue, kSecPublicKeyAttrs, pubd, kSecPrivateKeyAttrs, privd, NULL); CFReleaseNull(kzib); OSStatus status; ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), "Generate %ld bit (%ld byte) persistent RSA keypair", keySizeInBits, keySizeInBytes); CFReleaseNull(kgp); SKIP: { skip("keygen failed", 8, status == errSecSuccess); ok(pubKey, "pubkey returned"); ok(privKey, "privKey returned"); is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); SecKeyRef pubKey2, privKey2; CFDictionaryAddValue(pubd, kSecClass, kSecClassKey); CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(privd, kSecClass, kSecClassKey); CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue); ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2), "retrieve pub key by label"); ok(pubKey2, "got valid object"); ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2), "retrieve priv key by label and kSecAttrCanSign"); ok(privKey2, "got valid object"); /* Sign something. */ uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize); uint8_t sig[sigLen]; ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1, something, sizeof(something), sig, &sigLen), "sign something"); ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1, something, sizeof(something), sig, sigLen), "verify sig on something"); /* Cleanup. */ CFReleaseNull(pubKey2); CFReleaseNull(privKey2); } /* delete from keychain - note: do it before releasing publicName and privateName because pubd and privd have no retain/release callbacks */ ok_status(SecItemDelete(pubd), "delete generated pub key"); ok_status(SecItemDelete(privd), "delete generated priv key"); /* Cleanup. */ CFReleaseNull(pubKey); CFReleaseNull(privKey); CFReleaseNull(publicName); CFReleaseNull(privateName); CFReleaseNull(pubd); CFReleaseNull(privd); }
static void testkeygen(size_t keySizeInBits) { SecKeyRef pubKey = NULL, privKey = NULL; size_t keySizeInBytes = (keySizeInBits + 7) / 8; CFNumberRef kzib; int32_t keysz32 = (int32_t)keySizeInBits; kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC); CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); OSStatus status; ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), "Generate %ld bit (%ld byte) EC keypair", keySizeInBits, keySizeInBytes); CFRelease(kzib); CFRelease(kgp); SKIP: { skip("keygen failed", 8, status == errSecSuccess); ok(pubKey, "pubkey returned"); ok(privKey, "privKey returned"); is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); /* Sign something. */ uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; uint8_t sig[8+2*keySizeInBytes]; size_t sigLen = sizeof(sig); ok_status(SecKeyRawSign(privKey, kSecPaddingNone, something, sizeof(something), sig, &sigLen), "sign something"); ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone, something, sizeof(something), sig, sigLen), "verify sig on something"); testdigestandsign(privKey, pubKey); const void *privkeys[] = { kSecValueRef }; const void *privvalues[] = { privKey }; CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues, array_size(privkeys), NULL, NULL); ok_status(SecItemAdd(privitem, NULL), "add private key"); ok_status(SecItemDelete(privitem), "delete public key"); CFReleaseNull(privitem); const void *pubkeys[] = { kSecValueRef }; const void *pubvalues[] = { pubKey }; CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues, array_size(pubkeys), NULL, NULL); ok_status(SecItemAdd(pubitem, NULL), "add public key"); ok_status(SecItemDelete(pubitem), "delete public key"); CFReleaseNull(pubitem); /* Cleanup. */ CFReleaseNull(pubKey); CFReleaseNull(privKey); } }
static void tests(void) { CFDataRef message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, _user_one_p12, sizeof(_user_one_p12), kCFAllocatorNull); CFArrayRef items = NULL; SecCertificateRef cert = NULL; SecKeyRef pkey = NULL; is_status(SecPKCS12Import(message, NULL, NULL), errSecAuthFailed, "try null password on a known good p12"); CFStringRef password = CFSTR("user-one"); CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&kSecImportExportPassphrase, (const void **)&password, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecPKCS12Import(message, options, &items), "import user one"); is(CFArrayGetCount(items), 1, "one identity"); CFDictionaryRef item = CFArrayGetValueAtIndex(items, 0); SecIdentityRef identity = NULL; ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); CFReleaseNull(items); CFReleaseNull(message); CFReleaseNull(options); CFReleaseNull(password); CFReleaseNull(cert); CFReleaseNull(pkey); message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, _user_two_p12, sizeof(_user_two_p12), kCFAllocatorNull); items = NULL; password = CFSTR("user-two"); options = CFDictionaryCreate(NULL, (const void **)&kSecImportExportPassphrase, (const void **)&password, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecPKCS12Import(message, options, &items), "import user two"); is(CFArrayGetCount(items), 1, "one identity"); item = CFArrayGetValueAtIndex(items, 0); ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); CFReleaseNull(items); CFReleaseNull(message); CFReleaseNull(options); CFReleaseNull(password); CFReleaseNull(cert); CFReleaseNull(pkey); message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ECDSA_fails_import_p12, ECDSA_fails_import_p12_len, kCFAllocatorNull); items = NULL; password = CFSTR("test"); options = CFDictionaryCreate(NULL, (const void **)&kSecImportExportPassphrase, (const void **)&password, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecPKCS12Import(message, options, &items), "import ECDSA_fails_import_p12"); is(CFArrayGetCount(items), 1, "one identity"); item = CFArrayGetValueAtIndex(items, 0); ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data"); ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef"); ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key"); ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate"); CFDataRef pubdata = NULL; SecKeyRef pubkey = NULL; ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key"); ok(pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault, CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), kSecKeyEncodingBytes), "recreate seckey"); /* Sign something. */ uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; size_t sigLen = SecKeyGetSize(pkey, kSecKeySignatureSize); uint8_t sig[sigLen]; ok_status(SecKeyRawSign(pkey, kSecPaddingPKCS1, something, sizeof(something), sig, &sigLen), "sign something"); ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1, something, sizeof(something), sig, sigLen), "verify sig on something"); CFReleaseNull(pubdata); CFReleaseNull(pubkey); CFReleaseNull(pkey); ok(pkey = SecKeyCreateECPrivateKey(kCFAllocatorDefault, ECDSA_fails_import_priv_only, ECDSA_fails_import_priv_only_len, kSecKeyEncodingPkcs1), "import privkey without pub"); ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key"); ok(pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault, CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), kSecKeyEncodingBytes), "recreate seckey"); ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1, something, sizeof(something), sig, sigLen), "verify sig on something"); CFReleaseNull(pubdata); CFReleaseNull(pubkey); CFReleaseNull(pkey); CFReleaseNull(items); CFReleaseNull(message); CFReleaseNull(options); CFReleaseNull(password); CFReleaseNull(cert); }