]> git.saurik.com Git - apple/security.git/blob - OSX/shared_regressions/si-44-seckey-rsa.m
Security-59306.41.2.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/SecItemPriv.h>
29 #import <Security/oidsalg.h>
30
31 #import <corecrypto/ccrng.h>
32 #import <corecrypto/ccsha1.h>
33 #import <corecrypto/ccsha2.h>
34 #import <corecrypto/ccdigest.h>
35 #import <corecrypto/ccrsa.h>
36
37 #include "shared_regressions.h"
38
39 static NSData *decryptAndUnpad(SecKeyRef privateKey, SecKeyAlgorithm algorithm, NSData *ciphertext, NSError **error) {
40 NSData *plaintext = CFBridgingRelease(SecKeyCreateDecryptedData(privateKey, algorithm, (CFDataRef)ciphertext, (void *)error));
41 if (plaintext != nil && [(__bridge id)algorithm isEqual:(id)kSecKeyAlgorithmRSAEncryptionRaw]) {
42 NSRange range = NSMakeRange(0, plaintext.length);
43 while (((const UInt8 *)plaintext.bytes)[range.location] == 0x00 && range.location < plaintext.length) {
44 range.length--;
45 range.location++;
46 }
47 plaintext = [plaintext subdataWithRange:range];
48 }
49 return plaintext;
50 }
51
52 static void test_encrypt_run(SecKeyRef privateKey, SecKeyRef publicKey, SecKeyRef iosPrivateKey, SecKeyRef iosPublicKey, SecKeyAlgorithm algorithm) {
53 NSData *original = [NSData dataWithBytes:"encrypt" length:7], *plaintext;
54 NSError *error;
55
56 error = nil;
57 NSData *ciphertext = CFBridgingRelease(SecKeyCreateEncryptedData(publicKey, algorithm, (CFDataRef)original, (void *)&error));
58 ok(ciphertext != nil, "RSA encrypt (native) succeeded (error: %@, key %@)", error, publicKey);
59
60 error = nil;
61 NSData *iosCiphertext = CFBridgingRelease(SecKeyCreateEncryptedData(iosPublicKey, algorithm, (CFDataRef)original, (void *)&error));
62 ok(iosCiphertext != nil, "RSA encrypt (native) succeeded (error: %@, key %@)", error, iosPublicKey);
63
64 error = nil;
65 plaintext = decryptAndUnpad(privateKey, algorithm, ciphertext, &error);
66 ok(plaintext != nil, "RSA decrypt (native) succeeded (error: %@, key %@)", error, privateKey);
67 ok([plaintext isEqual:original], "(native -> native) plaintext equals original (%@ : %@)", original, plaintext);
68
69 error = nil;
70 plaintext = decryptAndUnpad(privateKey, algorithm, iosCiphertext, &error);
71 ok(plaintext != nil, "RSA decrypt (native) succeeded (error: %@, key %@)", error, privateKey);
72 ok([plaintext isEqual:original], "(ios -> native) plaintext equals original (%@ : %@)", original, plaintext);
73
74 error = nil;
75 plaintext = decryptAndUnpad(iosPrivateKey, algorithm, ciphertext, &error);
76 ok(plaintext != nil, "RSA decrypt (ios) succeeded (error: %@, key %@)", error, privateKey);
77 ok([plaintext isEqual:original], "(native -> ios) plaintext equals original (%@ : %@)", original, plaintext);
78
79 error = nil;
80 plaintext = decryptAndUnpad(iosPrivateKey, algorithm, iosCiphertext, &error);
81 ok(plaintext != nil, "RSA decrypt (ios) succeeded (error: %@, key %@)", error, privateKey);
82 ok([plaintext isEqual:original], "(ios -> ios) plaintext equals original (%@ : %@)", original, plaintext);
83 }
84 static const int TestCountEncryptRun = 10;
85
86 static void test_encrypt_keypair_run(int keySizeInBits, NSArray *algorithms, NSArray *failAlgorithms) {
87 NSError *error;
88 NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(keySizeInBits)};
89
90 error = nil;
91 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
92 ok(privateKey != nil, "generate private key (error %@)", error);
93
94 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
95 ok(publicKey != nil, "get public key");
96
97 NSData *data = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)privateKey, NULL));
98 NSDictionary *attrs = CFBridgingRelease(SecKeyCopyAttributes((SecKeyRef)privateKey));
99 error = nil;
100 id iosPrivateKey = CFBridgingRelease(SecKeyCreateWithData((CFDataRef)data, (CFDictionaryRef)attrs, (void *)&error));
101 ok(iosPrivateKey != nil, "get private key created from data");
102
103 data = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, NULL));
104 attrs = CFBridgingRelease(SecKeyCopyAttributes((SecKeyRef)publicKey));
105 error = nil;
106 id iosPublicKey = CFBridgingRelease(SecKeyCreateWithData((CFDataRef)data, (CFDictionaryRef)attrs, (void *)&error));
107 ok(iosPublicKey != nil, "get public key created from data");
108
109 for (id algorithm in algorithms) {
110 test_encrypt_run((__bridge SecKeyRef)privateKey, (__bridge SecKeyRef)publicKey,
111 (__bridge SecKeyRef)iosPrivateKey, (__bridge SecKeyRef)iosPublicKey,
112 (__bridge SecKeyAlgorithm)algorithm);
113 }
114
115 for (id algorithm in failAlgorithms) {
116 error = nil;
117 NSData *data = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, (SecKeyAlgorithm)algorithm, (CFDataRef)[NSData data], (void *)&error));
118 ok(data == nil && error.code == errSecParam, "incorrect algorithm refused");
119 }
120 }
121 static const int TestCountEncryptKeypairRun = 4;
122
123 static void test_encryption() {
124 test_encrypt_keypair_run(1024,
125 @[
126 (id)kSecKeyAlgorithmRSAEncryptionRaw,
127 (id)kSecKeyAlgorithmRSAEncryptionPKCS1,
128 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
129 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
130 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
131 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
132 ],
133 @[
134 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
135 ]);
136
137 test_encrypt_keypair_run(2048,
138 @[
139 (id)kSecKeyAlgorithmRSAEncryptionRaw,
140 (id)kSecKeyAlgorithmRSAEncryptionPKCS1,
141 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
142 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
143 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
144 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
145 (id)kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
146 ],
147 @[
148 ]);
149 }
150 static const int TestCountEncryption =
151 TestCountEncryptKeypairRun + (TestCountEncryptRun * 6) + (1 * 1) +
152 TestCountEncryptKeypairRun + (TestCountEncryptRun * 7) + (1 * 0);
153
154 static void test_pss_sign_run(SecKeyRef privateKey, SecKeyAlgorithm algorithm, SecKeyAlgorithm digestAlgorithm,
155 const struct ccdigest_info *di) {
156 NSError *error;
157 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey(privateKey));
158 NSData *message = [NSData dataWithBytes:"1234" length:4];
159 NSMutableData *digest = [NSMutableData dataWithLength:di->output_size];
160 ccdigest(di, message.length, message.bytes, digest.mutableBytes);
161
162 // Verify algorithm's availability
163 ok(SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, algorithm), "algorithm %@ available on key %@", algorithm, privateKey);
164 ok(SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, digestAlgorithm), "algorithm %@ available on key %@", digestAlgorithm, privateKey);
165
166 // Calculate signature of the message using SecKey
167 error = nil;
168 NSData *signature = CFBridgingRelease(SecKeyCreateSignature(privateKey, algorithm, (CFDataRef)message, (void *)&error));
169 ok(signature != nil, "sign message with algorithm %@: error %@", algorithm, error);
170
171 // Verify signature of the message using SecKey
172 error = nil;
173 Boolean verified = SecKeyVerifySignature((SecKeyRef)publicKey, algorithm, (CFDataRef)message, (CFDataRef)signature, (void *)&error);
174 ok(verified, "signature verified for algorithm %@: error %@", algorithm, error);
175
176 // Calculate signature of the digest using SecKey
177 error = nil;
178 signature = CFBridgingRelease(SecKeyCreateSignature(privateKey, digestAlgorithm, (CFDataRef)digest, (void *)&error));
179 ok(signature != nil, "sign digest with algorithm %@: error %@", digestAlgorithm, error);
180
181 // Verify signature of the digest using CC
182 NSData *pubData = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, (void *)&error));
183 ok(pubData != nil, "export public key: error %@", error);
184 cc_size n = ccrsa_import_pub_n(pubData.length, pubData.bytes);
185 ccrsa_pub_ctx_decl(ccn_sizeof_n(n), ccpub);
186 ccrsa_ctx_n(ccpub) = n;
187 int err = ccrsa_import_pub(ccpub, pubData.length, pubData.bytes);
188 is(err, 0, "ccrsa_import_pub(key=%@) failed", publicKey);
189
190 bool valid = false;
191 err = ccrsa_verify_pss(ccpub, di, di, di->output_size, digest.bytes, signature.length, signature.bytes, di->output_size, &valid);
192 is(err, 0, "ccrsa_verify_pss(%@) failed", algorithm);
193 ok(valid, "ccrsa verify signature (alg %@)", algorithm);
194
195 // Calculate signature of the digest using CC
196 error = nil;
197 NSData *privData = CFBridgingRelease(SecKeyCopyExternalRepresentation(privateKey, (void *)&error));
198 ok(privData != nil, "export private key: error %@", error);
199 n = ccrsa_import_priv_n(privData.length, privData.bytes);
200 ccrsa_full_ctx_decl(ccn_sizeof_n(n), ccpriv);
201 ccrsa_ctx_n(ccpriv) = n;
202 err = ccrsa_import_priv(ccpriv, privData.length, privData.bytes);
203 is(err, 0, "ccrsa_import_priv(key=%@) failed", privateKey);
204
205 NSMutableData *ccSig = [NSMutableData dataWithLength:SecKeyGetBlockSize(privateKey)];
206 size_t sigSize = ccSig.length;
207 err = ccrsa_sign_pss(ccpriv, di, di, di->output_size, ccrng(NULL), digest.length, digest.bytes, &sigSize, ccSig.mutableBytes);
208 is(err, 0, "ccrsa_sign_pss(%@) failed", digestAlgorithm);
209 is(sigSize, ccSig.length, "unexpected signature size for algorithm %@", digestAlgorithm);
210
211 // Verify signature of the digest using SecKey
212 error = nil;
213 verified = SecKeyVerifySignature((SecKeyRef)publicKey, digestAlgorithm, (CFDataRef)digest, (CFDataRef)ccSig, (void *)&error);
214 ok(verified, "signature verified for algorithm %@: error %@", digestAlgorithm, error);
215 }
216 static const int TestCountPSSSignRun = 14;
217
218 static void test_pss_sign() {
219 NSError *error;
220 NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @1024};
221
222 error = nil;
223 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
224 ok(privateKey != nil, "generate private key (error %@)", error);
225
226 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA1, kSecKeyAlgorithmRSASignatureDigestPSSSHA1, ccsha1_di());
227 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA224, kSecKeyAlgorithmRSASignatureDigestPSSSHA224, ccsha224_di());
228 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA256, kSecKeyAlgorithmRSASignatureDigestPSSSHA256, ccsha256_di());
229 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA384, kSecKeyAlgorithmRSASignatureDigestPSSSHA384, ccsha384_di());
230
231 // RSASSA-PSS requires hlen + slen + 2 size modulus, so it requires at least 1040bit keys, and should not be available for 1024b keys.
232 ok(!SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, kSecKeyAlgorithmRSASignatureDigestPSSSHA512));
233 ok(!SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, kSecKeyAlgorithmRSASignatureMessagePSSSHA512));
234
235 error = nil;
236 params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048};
237 privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
238 ok(privateKey != nil, "generate private key (error %@)", error);
239
240 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA1, kSecKeyAlgorithmRSASignatureDigestPSSSHA1, ccsha1_di());
241 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA224, kSecKeyAlgorithmRSASignatureDigestPSSSHA224, ccsha224_di());
242 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA256, kSecKeyAlgorithmRSASignatureDigestPSSSHA256, ccsha256_di());
243 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA384, kSecKeyAlgorithmRSASignatureDigestPSSSHA384, ccsha384_di());
244 test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA512, kSecKeyAlgorithmRSASignatureDigestPSSSHA512, ccsha512_di());
245 }
246 static const int TestCountPSSSign = 1 + TestCountPSSSignRun * 4 + 2 + 1 + TestCountPSSSignRun * 5;
247
248 static void test_bad_input(NSInteger keySizeInBits, NSInteger inputSize, SecKeyAlgorithm algorithm) {
249 NSError *error;
250 NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(keySizeInBits)};
251
252 error = nil;
253 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
254 ok(privateKey != nil, "generate private key (error %@)", error);
255 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
256
257 NSData *input, *output;
258
259 error = nil;
260 input = [NSMutableData dataWithLength:inputSize];
261 output = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, algorithm, (CFDataRef)input, (void *)&error));
262 ok(output, "encryption succeeds at the border size %d (key=%dbytes, %@)", (int)input.length, (int)keySizeInBits / 8, algorithm);
263 is((NSInteger)output.length, keySizeInBits / 8, "Unexpected output block size");
264
265 input = [NSMutableData dataWithLength:inputSize + 1];
266 output = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)publicKey, algorithm, (CFDataRef)input, (void *)&error));
267 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);
268 is_status((OSStatus)error.code, errSecParam, "Fails with errSecParam for too long input (%@)", algorithm);
269 }
270 static const int TestCountBadInputSizeStep = 5;
271
272 static void test_bad_input_size() {
273 test_bad_input(1024, 128, kSecKeyAlgorithmRSAEncryptionRaw);
274 test_bad_input(2048, 256, kSecKeyAlgorithmRSAEncryptionRaw);
275 test_bad_input(1024, 128 - 11, kSecKeyAlgorithmRSAEncryptionPKCS1);
276 test_bad_input(2048, 256 - 11, kSecKeyAlgorithmRSAEncryptionPKCS1);
277 test_bad_input(1024, 128 - 42, kSecKeyAlgorithmRSAEncryptionOAEPSHA1);
278 test_bad_input(2048, 256 - 42, kSecKeyAlgorithmRSAEncryptionOAEPSHA1);
279 test_bad_input(1024, 128 - 66, kSecKeyAlgorithmRSAEncryptionOAEPSHA256);
280 test_bad_input(2048, 256 - 66, kSecKeyAlgorithmRSAEncryptionOAEPSHA256);
281 }
282 static const int TestCountBadInputSize = TestCountBadInputSizeStep * 8;
283
284 static void test_bad_signature() {
285 NSDictionary *params = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048 };
286 NSError *error;
287 id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error));
288 ok(privateKey, "Generate RSA-2048 temporary key, err %@", error);
289 id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey));
290 ok(publicKey, "Get public key from private key");
291
292 #if TARGET_OS_IPHONE
293 SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1;
294 #else
295 SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1;
296 #endif
297
298 char digest[20] = "digest";
299 NSData *digestData = [NSData dataWithBytes:digest length:sizeof(digest)];
300 NSData *signature = CFBridgingRelease(SecKeyCreateSignature((SecKeyRef)privateKey, algorithm, (CFDataRef)digestData, (void *)&error));
301 ok(signature, "Sign digest, err %@", error);
302
303 bool result = SecKeyVerifySignature((SecKeyRef)publicKey, algorithm, (CFDataRef)digestData, (CFDataRef)signature, (void *)&error);
304 ok(result, "Verify signature, err %@", error);
305
306 OSStatus status = SecKeyRawVerify((SecKeyRef)publicKey, kSecPaddingPKCS1SHA1, (const uint8_t *)digest, sizeof(digest), signature.bytes, signature.length);
307 ok_status(status, "Raw verify correct signature");
308
309 status = SecKeyRawVerify((SecKeyRef)publicKey, kSecPaddingPKCS1SHA1, (const uint8_t *)digest, sizeof(digest), (void * _Nonnull)NULL, 0);
310 is_status(status, errSSLCrypto, "NULL signature failure");
311
312 const SecAsn1AlgId algId = { .algorithm = CSSMOID_SHA1WithRSA };
313 signature = CFBridgingRelease(SecKeyCreateSignature((SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, (CFDataRef)digestData, (void *)&error));
314 ok(signature, "Sign message, err %@", error);
315
316 status = SecKeyDigestAndVerify((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), signature.bytes, signature.length);
317 ok_status(status, "Raw verify correct signature");
318
319 status = SecKeyDigestAndVerify((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), (void * _Nonnull)NULL, 0);
320 is_status(status, errSSLCrypto, "NULL signature failure");
321
322 signature = CFBridgingRelease(SecKeyCreateSignature((SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, (CFDataRef)digestData, (void *)&error));
323 ok(signature, "Sign message, err %@", error);
324
325 status = SecKeyVerifyDigest((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), signature.bytes, signature.length);
326 ok_status(status, "Raw verify correct signature");
327
328 status = SecKeyVerifyDigest((__bridge SecKeyRef)publicKey, &algId, (const uint8_t *)digest, sizeof(digest), (void * _Nonnull)NULL, 0);
329 is_status(status, errSSLCrypto, "NULL signature failure");
330 }
331 static const int TestCountBadSignature = 12;
332
333 static const int TestCount =
334 TestCountEncryption +
335 TestCountPSSSign +
336 TestCountBadInputSize +
337 TestCountBadSignature;
338
339 int si_44_seckey_rsa(int argc, char *const *argv) {
340 plan_tests(TestCount);
341
342 @autoreleasepool {
343 test_encryption();
344 test_pss_sign();
345 test_bad_input_size();
346 test_bad_signature();
347 }
348
349 return 0;
350 }