2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #import <Foundation/Foundation.h>
27 #include "shared_regressions.h"
29 static NSData *decryptAndUnpad(SecKeyRef privateKey, SecKeyAlgorithm algorithm, NSData *ciphertext, NSError **error) {
30 NSData *plaintext = CFBridgingRelease(SecKeyCreateDecryptedData(privateKey, algorithm, (CFDataRef)ciphertext, (void *)error));
31 if (plaintext != nil && [(__bridge id)algorithm isEqual:(id)kSecKeyAlgorithmRSAEncryptionRaw]) {
32 NSRange range = NSMakeRange(0, plaintext.length);
33 while (((const UInt8 *)plaintext.bytes)[range.location] == 0x00 && range.location < plaintext.length) {
37 plaintext = [plaintext subdataWithRange:range];
42 static void test_encrypt_run(SecKeyRef privateKey, SecKeyRef publicKey, SecKeyRef iosPrivateKey, SecKeyRef iosPublicKey, SecKeyAlgorithm algorithm) {
43 NSData *original = [NSData dataWithBytes:"encrypt" length:7], *plaintext;
47 NSData *ciphertext = CFBridgingRelease(SecKeyCreateEncryptedData(publicKey, algorithm, (CFDataRef)original, (void *)&error));
48 ok(ciphertext != nil, "RSA encrypt (native) succeeded (error: %@, key %@)", error, publicKey);
51 NSData *iosCiphertext = CFBridgingRelease(SecKeyCreateEncryptedData(iosPublicKey, algorithm, (CFDataRef)original, (void *)&error));
52 ok(iosCiphertext != nil, "RSA encrypt (native) succeeded (error: %@, key %@)", error, iosPublicKey);
55 plaintext = decryptAndUnpad(privateKey, algorithm, ciphertext, &error);
56 ok(plaintext != nil, "RSA decrypt (native) succeeded (error: %@, key %@)", error, privateKey);
57 ok([plaintext isEqual:original], "(native -> native) plaintext equals original (%@ : %@)", original, plaintext);
60 plaintext = decryptAndUnpad(privateKey, algorithm, iosCiphertext, &error);
61 ok(plaintext != nil, "RSA decrypt (native) succeeded (error: %@, key %@)", error, privateKey);
62 ok([plaintext isEqual:original], "(ios -> native) plaintext equals original (%@ : %@)", original, plaintext);
65 plaintext = decryptAndUnpad(iosPrivateKey, algorithm, ciphertext, &error);
66 ok(plaintext != nil, "RSA decrypt (ios) succeeded (error: %@, key %@)", error, privateKey);
67 ok([plaintext isEqual:original], "(native -> ios) plaintext equals original (%@ : %@)", original, plaintext);
70 plaintext = decryptAndUnpad(iosPrivateKey, algorithm, iosCiphertext, &error);
71 ok(plaintext != nil, "RSA decrypt (ios) succeeded (error: %@, key %@)", error, privateKey);
72 ok([plaintext isEqual:original], "(ios -> ios) plaintext equals original (%@ : %@)", original, plaintext);
74 static const int TestCountEncryptRun = 10;
76 static void test_encrypt_keypair_run(int keySizeInBits, NSArray *algorithms, NSArray *failAlgorithms) {
78 NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(keySizeInBits)};
81 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
82 ok(privateKey != nil, "generate private key (error %@)", error);
84 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
85 ok(publicKey != nil, "get public key");
87 NSData *data = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)privateKey, NULL));
88 NSDictionary *attrs = CFBridgingRelease(SecKeyCopyAttributes((SecKeyRef)privateKey));
90 id iosPrivateKey = CFBridgingRelease(SecKeyCreateWithData((CFDataRef)data, (CFDictionaryRef)attrs, (void *)&error));
91 ok(iosPrivateKey != nil, "get private key created from data");
93 data = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, NULL));
94 attrs = CFBridgingRelease(SecKeyCopyAttributes((SecKeyRef)publicKey));
96 id iosPublicKey = CFBridgingRelease(SecKeyCreateWithData((CFDataRef)data, (CFDictionaryRef)attrs, (void *)&error));
97 ok(iosPublicKey != nil, "get public key created from data");
99 for (id algorithm in algorithms) {
100 test_encrypt_run((__bridge SecKeyRef)privateKey, (__bridge SecKeyRef)publicKey,
101 (__bridge SecKeyRef)iosPrivateKey, (__bridge SecKeyRef)iosPublicKey,
102 (__bridge SecKeyAlgorithm)algorithm);
105 for (id algorithm in failAlgorithms) {
107 NSData *data = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, (SecKeyAlgorithm)algorithm, (CFDataRef)[NSData data], (void *)&error));
108 ok(data == nil && error.code == errSecParam, "incorrect algorithm refused");
111 static const int TestCountEncryptKeypairRun = 4;
113 static void test_encryption() {
114 test_encrypt_keypair_run(1024,
116 (id)kSecKeyAlgorithmRSAEncryptionRaw,
117 (id)kSecKeyAlgorithmRSAEncryptionPKCS1,
118 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
119 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
120 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
121 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
124 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
127 test_encrypt_keypair_run(2048,
129 (id)kSecKeyAlgorithmRSAEncryptionRaw,
130 (id)kSecKeyAlgorithmRSAEncryptionPKCS1,
131 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
132 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
133 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
134 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
135 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
140 static const int TestCountEncryption =
141 TestCountEncryptKeypairRun + (TestCountEncryptRun * 6) + (1 * 1) +
142 TestCountEncryptKeypairRun + (TestCountEncryptRun * 7) + (1 * 0);
144 static const int TestCount = TestCountEncryption;
145 int si_44_seckey_rsa(int argc, char *const *argv) {
146 plan_tests(TestCount);