1#include <Security/Security.h> 2#include <Security/SecKeyPriv.h> 3#include <Security/SecItem.h> 4#include <CoreFoundation/CoreFoundation.h> 5#include <stdlib.h> 6#include <unistd.h> 7 8#include "testmore.h" 9#include "testenv.h" 10#include "testcssm.h" 11#include "testleaks.h" 12 13 14void AddKeyCFTypePairToDictionary(CFMutableDictionaryRef mdr, CFTypeRef key, CFTypeRef value) 15{ 16 CFDictionaryAddValue(mdr, key, value); 17} 18 19 20 21void AddKeyNumberPairToDictionary(CFMutableDictionaryRef mdr, CFTypeRef key, uint32 value) 22{ 23 // make a CFNumber out of the value 24 CFNumberRef number = CFNumberCreate(NULL, kCFNumberSInt32Type, &value); 25 CFDictionaryAddValue(mdr, key, number); 26 CFRelease(number); 27} 28 29 30 31void AddKeyStringPairToDictionary(CFMutableDictionaryRef mdr, CFTypeRef key, const char* string) 32{ 33 // We add the string as a CFData 34 CFDataRef data = CFDataCreate(NULL, (const UInt8*) string, strlen(string)); 35 CFDictionaryAddValue(mdr, key, data); 36 CFRelease(data); 37} 38 39 40 41int SignVerifyTest() 42{ 43 CFMutableDictionaryRef parameters; 44 SecKeyRef publicKey, privateKey; 45 46 // start out with an empty dictionary and see if it returns an error 47 parameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 48 OSStatus result = SecKeyGeneratePair(parameters, &publicKey, &privateKey); 49 50 ok(result != noErr, "result is noErr"); 51 52 // add the algorithm type 53 AddKeyCFTypePairToDictionary(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA); 54 55 // see if we can get a 2048 bit keypair 56 AddKeyNumberPairToDictionary(parameters, kSecAttrKeySizeInBits, 2048); 57 58 // put an application tag on the key 59 AddKeyStringPairToDictionary(parameters, kSecAttrApplicationTag, "This is a test."); 60 61 // try again 62 result = SecKeyGeneratePair(parameters, &publicKey, &privateKey); 63 ok_status(result, "SecKeyGeneratePair"); 64 if (result != noErr) 65 { 66 return 1; 67 } 68 69 // Make a chunk of data 70 char data[] = "This is a test of some data. Ain't it grand?"; 71 72 SecPadding paddings[] = {kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingPKCS1MD2, kSecPaddingPKCS1MD5, kSecPaddingPKCS1SHA1}; 73 const int numberOfPaddings = sizeof(paddings) / sizeof (SecPadding); 74 75 // test each padding mode 76 int n; 77 for (n = 0; n < numberOfPaddings; ++n) 78 { 79 // sign that data with the private key 80 uint8 signature[512]; 81 size_t signatureLength = sizeof(signature); 82 83 result = SecKeyRawSign(privateKey, paddings[n], (uint8_t*) data, strlen(data), signature, &signatureLength); 84 ok_status(result, "SecKeyRawSign"); 85 86 // verify with the signature 87 result = SecKeyRawVerify(publicKey, paddings[n], (uint8_t*) data, strlen(data), signature, signatureLength); 88 ok_status(result, "SecKeyRawVerify"); 89 } 90 91 // clean up 92 SecKeychainItemDelete((SecKeychainItemRef) publicKey); 93 SecKeychainItemDelete((SecKeychainItemRef) privateKey); 94 95 CFRelease(publicKey); 96 CFRelease(privateKey); 97 CFRelease(parameters); 98 99 return 0; 100} 101 102int SignVerifyWithAsyncTest() 103{ 104 CFMutableDictionaryRef parameters; 105 __block SecKeyRef publicKey, privateKey; 106 107 // start out with an empty dictionary and see if it returns an error 108 parameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 109 OSStatus result = SecKeyGeneratePair(parameters, &publicKey, &privateKey); 110 dispatch_group_t everyone_called = dispatch_group_create(); 111 112 dispatch_group_enter(everyone_called); 113 SecKeyGeneratePairAsync(parameters, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(SecKeyRef publicKey, SecKeyRef privateKey, CFErrorRef error){ 114 ok(publicKey == NULL && privateKey == NULL, "keys are NULL"); 115 ok(error != NULL, "error set"); 116 dispatch_group_leave(everyone_called); 117 }); 118 119 // add the algorithm type 120 AddKeyCFTypePairToDictionary(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA); 121 122 // see if we can get a 2048 bit keypair 123 AddKeyNumberPairToDictionary(parameters, kSecAttrKeySizeInBits, 2048); 124 125 // put an application tag on the key 126 AddKeyStringPairToDictionary(parameters, kSecAttrApplicationTag, "This is a test."); 127 128 // throw some sort of access thingie on it too 129 SecAccessRef access = NULL; 130 SecTrustedApplicationRef myself = NULL; 131 ok_status(SecTrustedApplicationCreateFromPath(NULL, &myself), "create trusted app for self"); 132 CFArrayRef trustedApplications = CFArrayCreate(NULL, (const void **)&myself, 1, &kCFTypeArrayCallBacks); 133 ok_status(SecAccessCreate(CFSTR("Trust self (test)"), trustedApplications, &access), "SecAccessCreate"); 134 CFRelease(trustedApplications); 135 CFRelease(myself); 136 AddKeyCFTypePairToDictionary(parameters, kSecAttrAccess, access); 137 138 // try again 139 dispatch_group_enter(everyone_called); 140 SecKeyGeneratePairAsync(parameters, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(SecKeyRef pubKey, SecKeyRef privKey, CFErrorRef error){ 141 ok(pubKey != NULL && privKey != NULL, "keys set"); 142 ok(error == NULL, "no error"); 143 publicKey = (SecKeyRef)CFRetain(pubKey); 144 privateKey = (SecKeyRef)CFRetain(privKey); 145 dispatch_group_leave(everyone_called); 146 }); 147 148 dispatch_group_wait(everyone_called, DISPATCH_TIME_FOREVER); 149 if (NULL == publicKey || NULL == privateKey) 150 { 151 return 1; 152 } 153 154 // Make a chunk of data 155 char data[] = "This is a test of some data. Ain't it grand?"; 156 157 SecPadding paddings[] = {kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingPKCS1MD2, kSecPaddingPKCS1MD5, kSecPaddingPKCS1SHA1}; 158 const int numberOfPaddings = sizeof(paddings) / sizeof (SecPadding); 159 160 // test each padding mode 161 int n; 162 for (n = 0; n < numberOfPaddings; ++n) 163 { 164 // sign that data with the private key 165 uint8 signature[512]; 166 size_t signatureLength = sizeof(signature); 167 168 result = SecKeyRawSign(privateKey, paddings[n], (uint8_t*) data, strlen(data), signature, &signatureLength); 169 ok_status(result, "SecKeyRawSign"); 170 171 // verify with the signature 172 result = SecKeyRawVerify(publicKey, paddings[n], (uint8_t*) data, strlen(data), signature, signatureLength); 173 ok_status(result, "SecKeyRawVerify"); 174 } 175 176 // clean up 177 SecKeychainItemDelete((SecKeychainItemRef) publicKey); 178 SecKeychainItemDelete((SecKeychainItemRef) privateKey); 179 180 CFRelease(publicKey); 181 CFRelease(privateKey); 182 CFRelease(parameters); 183 184 return 0; 185} 186 187 188 189int EncryptDecryptTest() 190{ 191 CFMutableDictionaryRef parameters; 192 SecKeyRef encryptionKey, decryptionKey; 193 194 // start out with an empty dictionary and see if it returns an error 195 parameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 196 197 // add the algorithm type 198 AddKeyCFTypePairToDictionary(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA); 199 200 // see if we can get a 2048 bit keypair 201 AddKeyNumberPairToDictionary(parameters, kSecAttrKeySizeInBits, 2048); 202 203 // put an application tag on the key 204 AddKeyStringPairToDictionary(parameters, kSecAttrApplicationTag, "This is a test."); 205 206 OSStatus result = SecKeyGeneratePair(parameters, &encryptionKey, &decryptionKey); 207 ok_status(result, "EncryptDecryptTest"); 208 209 // Make a chunk of data 210 char data[] = "I want to keep this data secure."; 211 212 SecPadding paddings[] = {kSecPaddingPKCS1}; 213 const int numberOfPaddings = sizeof(paddings) / sizeof (SecPadding); 214 215 // test each padding mode 216 int n; 217 for (n = 0; n < numberOfPaddings; ++n) 218 { 219 // encrypt that data with the public key 220 uint8 encryptedData[2048]; 221 size_t encryptedDataLength = sizeof(encryptedData); 222 memset(encryptedData, 0xFF, encryptedDataLength); 223 224 result = SecKeyEncrypt(encryptionKey, paddings[n], (uint8_t*) data, sizeof(data), encryptedData, &encryptedDataLength); 225 if (result != noErr) 226 { 227 fprintf(stderr, "Error in encryption.\n"); 228 cssmPerror(NULL, result); 229 return 1; 230 } 231 232 uint8 decryptedData[2048]; 233 size_t decryptedDataLength = sizeof(decryptedData); 234 235 // decrypt with the private key 236 result = SecKeyDecrypt(decryptionKey, paddings[n], encryptedData, encryptedDataLength, decryptedData, &decryptedDataLength); 237 ok_status(result, "SecKeyDecrypt"); 238 239 // what we got back had better equal what we put in 240 if (memcmp(data, decryptedData, sizeof(data)) != 0) 241 { 242 fprintf(stderr, "Decrypted text != original plain text.\n"); 243 return 1; 244 } 245 } 246 247 // clean up 248 SecKeychainItemDelete((SecKeychainItemRef) encryptionKey); 249 SecKeychainItemDelete((SecKeychainItemRef) decryptionKey); 250 251 CFRelease(encryptionKey); 252 CFRelease(decryptionKey); 253 CFRelease(parameters); 254 255 return 0; 256} 257 258 259 260#define TEST_ITEM_ACCOUNT CFSTR("SecItemTest_Account") 261#define TEST_ITEM_SERVICE CFSTR("SecItemTest_Service") 262 263int SecItemTest() 264{ 265 // create a dictionary to hold the item 266 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 267 268 // create our item -- we are only testing generic passwords, since that is the scope of the bug 269 CFDictionaryAddValue(dict, kSecClass, kSecClassGenericPassword); 270 CFDictionaryAddValue(dict, kSecAttrAccount, TEST_ITEM_ACCOUNT); 271 CFDictionaryAddValue(dict, kSecAttrService, TEST_ITEM_SERVICE); 272 273 const char* data = "Shh! It's a secret!!!"; 274 CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8*) data, strlen(data), NULL); 275 CFDictionaryAddValue(dict, kSecValueData, dataRef); 276 277 CFTypeRef itemRef; 278 OSStatus result = SecItemAdd(dict, &itemRef); 279 ok_status(result, "SecItemAdd"); 280 281 // cleanup 282 CFRelease(dict); 283 284 // search for the item 285 dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 286 287 // create our item -- we are only testing generic passwords, since that is the scope of the bug 288 CFDictionaryAddValue(dict, kSecClass, kSecClassGenericPassword); 289 CFDictionaryAddValue(dict, kSecAttrAccount, TEST_ITEM_ACCOUNT); 290 CFDictionaryAddValue(dict, kSecAttrService, TEST_ITEM_SERVICE); 291 CFDictionaryAddValue(dict, kSecReturnAttributes, kCFBooleanTrue); 292 293 result = SecItemCopyMatching(dict, &itemRef); 294 ok_status(result, "SecItemCopyMatching"); 295 296 return 0; 297} 298 299 300 301void tests() 302{ 303 SecKeychainRef keychain = NULL; 304 ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "SecKeychainSetUserInteractionAllowed(FALSE)"); 305 ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), "SecKeychainCreate"); 306 307 SignVerifyWithAsyncTest(); 308 SignVerifyTest(); 309 SecItemTest(); 310 311 if (keychain) CFRelease(keychain); 312} 313 314 315 316int main(int argc, char * const *argv) 317{ 318 plan_tests(34); 319 if (!tests_begin(argc, argv)) 320 BAIL_OUT("tests_begin failed"); 321 tests(); 322 ok(tests_end(1), "cleanup"); 323 ok_leaks("no leaks"); 324 return 0; 325} 326