]> git.saurik.com Git - apple/security.git/blob - OSX/shared_regressions/si-44-seckey-rsa.m
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / shared_regressions / si-44-seckey-rsa.m
1 /*
2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #import <Foundation/Foundation.h>
26
27 #import <Security/SecKeyPriv.h>
28 #import <Security/oidsalg.h>
29
30 #include "shared_regressions.h"
31
32 static NSData *decryptAndUnpad(SecKeyRef privateKey, SecKeyAlgorithm algorithm, NSData *ciphertext, NSError **error) {
33 NSData *plaintext = CFBridgingRelease(SecKeyCreateDecryptedData(privateKey, algorithm, (CFDataRef)ciphertext, (void *)error));
34 if (plaintext != nil && [(__bridge id)algorithm isEqual:(id)kSecKeyAlgorithmRSAEncryptionRaw]) {
35 NSRange range = NSMakeRange(0, plaintext.length);
36 while (((const UInt8 *)plaintext.bytes)[range.location] == 0x00 && range.location < plaintext.length) {
37 range.length--;
38 range.location++;
39 }
40 plaintext = [plaintext subdataWithRange:range];
41 }
42 return plaintext;
43 }
44
45 static void test_encrypt_run(SecKeyRef privateKey, SecKeyRef publicKey, SecKeyRef iosPrivateKey, SecKeyRef iosPublicKey, SecKeyAlgorithm algorithm) {
46 NSData *original = [NSData dataWithBytes:"encrypt" length:7], *plaintext;
47 NSError *error;
48
49 error = nil;
50 NSData *ciphertext = CFBridgingRelease(SecKeyCreateEncryptedData(publicKey, algorithm, (CFDataRef)original, (void *)&error));
51 ok(ciphertext != nil, "RSA encrypt (native) succeeded (error: %@, key %@)", error, publicKey);
52
53 error = nil;
54 NSData *iosCiphertext = CFBridgingRelease(SecKeyCreateEncryptedData(iosPublicKey, algorithm, (CFDataRef)original, (void *)&error));
55 ok(iosCiphertext != nil, "RSA encrypt (native) succeeded (error: %@, key %@)", error, iosPublicKey);
56
57 error = nil;
58 plaintext = decryptAndUnpad(privateKey, algorithm, ciphertext, &error);
59 ok(plaintext != nil, "RSA decrypt (native) succeeded (error: %@, key %@)", error, privateKey);
60 ok([plaintext isEqual:original], "(native -> native) plaintext equals original (%@ : %@)", original, plaintext);
61
62 error = nil;
63 plaintext = decryptAndUnpad(privateKey, algorithm, iosCiphertext, &error);
64 ok(plaintext != nil, "RSA decrypt (native) succeeded (error: %@, key %@)", error, privateKey);
65 ok([plaintext isEqual:original], "(ios -> native) plaintext equals original (%@ : %@)", original, plaintext);
66
67 error = nil;
68 plaintext = decryptAndUnpad(iosPrivateKey, algorithm, ciphertext, &error);
69 ok(plaintext != nil, "RSA decrypt (ios) succeeded (error: %@, key %@)", error, privateKey);
70 ok([plaintext isEqual:original], "(native -> ios) plaintext equals original (%@ : %@)", original, plaintext);
71
72 error = nil;
73 plaintext = decryptAndUnpad(iosPrivateKey, algorithm, iosCiphertext, &error);
74 ok(plaintext != nil, "RSA decrypt (ios) succeeded (error: %@, key %@)", error, privateKey);
75 ok([plaintext isEqual:original], "(ios -> ios) plaintext equals original (%@ : %@)", original, plaintext);
76 }
77 static const int TestCountEncryptRun = 10;
78
79 static void test_encrypt_keypair_run(int keySizeInBits, NSArray *algorithms, NSArray *failAlgorithms) {
80 NSError *error;
81 NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(keySizeInBits)};
82
83 error = nil;
84 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
85 ok(privateKey != nil, "generate private key (error %@)", error);
86
87 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
88 ok(publicKey != nil, "get public key");
89
90 NSData *data = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)privateKey, NULL));
91 NSDictionary *attrs = CFBridgingRelease(SecKeyCopyAttributes((SecKeyRef)privateKey));
92 error = nil;
93 id iosPrivateKey = CFBridgingRelease(SecKeyCreateWithData((CFDataRef)data, (CFDictionaryRef)attrs, (void *)&error));
94 ok(iosPrivateKey != nil, "get private key created from data");
95
96 data = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, NULL));
97 attrs = CFBridgingRelease(SecKeyCopyAttributes((SecKeyRef)publicKey));
98 error = nil;
99 id iosPublicKey = CFBridgingRelease(SecKeyCreateWithData((CFDataRef)data, (CFDictionaryRef)attrs, (void *)&error));
100 ok(iosPublicKey != nil, "get public key created from data");
101
102 for (id algorithm in algorithms) {
103 test_encrypt_run((__bridge SecKeyRef)privateKey, (__bridge SecKeyRef)publicKey,
104 (__bridge SecKeyRef)iosPrivateKey, (__bridge SecKeyRef)iosPublicKey,
105 (__bridge SecKeyAlgorithm)algorithm);
106 }
107
108 for (id algorithm in failAlgorithms) {
109 error = nil;
110 NSData *data = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, (SecKeyAlgorithm)algorithm, (CFDataRef)[NSData data], (void *)&error));
111 ok(data == nil && error.code == errSecParam, "incorrect algorithm refused");
112 }
113 }
114 static const int TestCountEncryptKeypairRun = 4;
115
116 static void test_encryption() {
117 test_encrypt_keypair_run(1024,
118 @[
119 (id)kSecKeyAlgorithmRSAEncryptionRaw,
120 (id)kSecKeyAlgorithmRSAEncryptionPKCS1,
121 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
122 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
123 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
124 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
125 ],
126 @[
127 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
128 ]);
129
130 test_encrypt_keypair_run(2048,
131 @[
132 (id)kSecKeyAlgorithmRSAEncryptionRaw,
133 (id)kSecKeyAlgorithmRSAEncryptionPKCS1,
134 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
135 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
136 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
137 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
138 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
139 ],
140 @[
141 ]);
142 }
143 static const int TestCountEncryption =
144 TestCountEncryptKeypairRun + (TestCountEncryptRun * 6) + (1 * 1) +
145 TestCountEncryptKeypairRun + (TestCountEncryptRun * 7) + (1 * 0);
146
147 static void test_bad_input(NSInteger keySizeInBits, NSInteger inputSize, SecKeyAlgorithm algorithm) {
148 NSError *error;
149 NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(keySizeInBits)};
150
151 error = nil;
152 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
153 ok(privateKey != nil, "generate private key (error %@)", error);
154 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
155
156 NSData *input, *output;
157
158 error = nil;
159 input = [NSMutableData dataWithLength:inputSize];
160 output = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, algorithm, (CFDataRef)input, (void *)&error));
161 ok(output, "encryption succeeds at the border size %d (key=%dbytes, %@)", (int)input.length, (int)keySizeInBits / 8, algorithm);
162 is((NSInteger)output.length, keySizeInBits / 8, "Unexpected output block size");
163
164 input = [NSMutableData dataWithLength:inputSize + 1];
165 output = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, algorithm, (CFDataRef)input, (void *)&error));
166 ok(output == nil, "encryption did not fail for border size %d (key=%dbytes, output=%dbytes, %@)", (int)input.length, (int)keySizeInBits / 8, (int)output.length, algorithm);
167 is_status((OSStatus)error.code, errSecParam, "Fails with errSecParam for too long input (%@)", algorithm);
168 }
169 static const int TestCountBadInputSizeStep = 5;
170
171 static void test_bad_input_size() {
172 test_bad_input(1024, 128, kSecKeyAlgorithmRSAEncryptionRaw);
173 test_bad_input(2048, 256, kSecKeyAlgorithmRSAEncryptionRaw);
174 test_bad_input(1024, 128 - 11, kSecKeyAlgorithmRSAEncryptionPKCS1);
175 test_bad_input(2048, 256 - 11, kSecKeyAlgorithmRSAEncryptionPKCS1);
176 test_bad_input(1024, 128 - 42, kSecKeyAlgorithmRSAEncryptionOAEPSHA1);
177 test_bad_input(2048, 256 - 42, kSecKeyAlgorithmRSAEncryptionOAEPSHA1);
178 test_bad_input(1024, 128 - 66, kSecKeyAlgorithmRSAEncryptionOAEPSHA256);
179 test_bad_input(2048, 256 - 66, kSecKeyAlgorithmRSAEncryptionOAEPSHA256);
180 }
181 static const int TestCountBadInputSize = TestCountBadInputSizeStep * 8;
182
183 static void test_bad_signature() {
184 NSDictionary *params = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048 };
185 NSError *error;
186 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
187 ok(privateKey, "Generate RSA-2048 temporary key, err %@", error);
188 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
189 ok(publicKey, "Get public key from private key");
190
191 #if TARGET_OS_IPHONE
192 SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1;
193 #else
194 SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1;
195 #endif
196
197 char digest[20] = "digest";
198 NSData *digestData = [NSData dataWithBytes:digest length:sizeof(digest)];
199 NSData *signature = CFBridgingRelease(SecKeyCreateSignature((SecKeyRef)privateKey, algorithm, (CFDataRef)digestData, (void *)&error));
200 ok(signature, "Sign digest, err %@", error);
201
202 bool result = SecKeyVerifySignature((SecKeyRef)publicKey, algorithm, (CFDataRef)digestData, (CFDataRef)signature, (void *)&error);
203 ok(result, "Verify signature, err %@", error);
204
205 OSStatus status = SecKeyRawVerify((SecKeyRef)publicKey, kSecPaddingPKCS1SHA1, (const uint8_t *)digest, sizeof(digest), signature.bytes, signature.length);
206 ok_status(status, "Raw verify correct signature");
207
208 status = SecKeyRawVerify((SecKeyRef)publicKey, kSecPaddingPKCS1SHA1, (const uint8_t *)digest, sizeof(digest), (void * _Nonnull)NULL, 0);
209 is_status(status, errSSLCrypto, "NULL signature failure");
210
211 const SecAsn1AlgId algId = { .algorithm = CSSMOID_SHA1WithRSA };
212 signature = CFBridgingRelease(SecKeyCreateSignature((SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, (CFDataRef)digestData, (void *)&error));
213 ok(signature, "Sign message, err %@", error);
214
215 status = SecKeyDigestAndVerify((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), signature.bytes, signature.length);
216 ok_status(status, "Raw verify correct signature");
217
218 status = SecKeyDigestAndVerify((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), (void * _Nonnull)NULL, 0);
219 is_status(status, errSSLCrypto, "NULL signature failure");
220
221 signature = CFBridgingRelease(SecKeyCreateSignature((SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, (CFDataRef)digestData, (void *)&error));
222 ok(signature, "Sign message, err %@", error);
223
224 status = SecKeyVerifyDigest((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), signature.bytes, signature.length);
225 ok_status(status, "Raw verify correct signature");
226
227 status = SecKeyVerifyDigest((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), (void * _Nonnull)NULL, 0);
228 is_status(status, errSSLCrypto, "NULL signature failure");
229 }
230 static const int TestCountBadSignature = 12;
231
232 static const int TestCount =
233 TestCountEncryption +
234 TestCountBadInputSize +
235 TestCountBadSignature;
236
237 int si_44_seckey_rsa(int argc, char *const *argv) {
238 plan_tests(TestCount);
239
240 @autoreleasepool {
241 test_encryption();
242 test_bad_input_size();
243 test_bad_signature();
244 }
245
246 return 0;
247 }