X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/914fc88e61be54aed6b18205ff2775b48793a3b6..866f8763175ff60e4fa455b92b5eb660a12fe6c7:/OSX/shared_regressions/si-44-seckey-rsa.m?ds=sidebyside diff --git a/OSX/shared_regressions/si-44-seckey-rsa.m b/OSX/shared_regressions/si-44-seckey-rsa.m index b41a37e0..23f58798 100644 --- a/OSX/shared_regressions/si-44-seckey-rsa.m +++ b/OSX/shared_regressions/si-44-seckey-rsa.m @@ -25,8 +25,15 @@ #import #import +#import #import +#import +#import +#import +#import +#import + #include "shared_regressions.h" static NSData *decryptAndUnpad(SecKeyRef privateKey, SecKeyAlgorithm algorithm, NSData *ciphertext, NSError **error) { @@ -144,6 +151,100 @@ static const int TestCountEncryption = TestCountEncryptKeypairRun + (TestCountEncryptRun * 6) + (1 * 1) + TestCountEncryptKeypairRun + (TestCountEncryptRun * 7) + (1 * 0); +static void test_pss_sign_run(SecKeyRef privateKey, SecKeyAlgorithm algorithm, SecKeyAlgorithm digestAlgorithm, + const struct ccdigest_info *di) { + NSError *error; + id publicKey = CFBridgingRelease(SecKeyCopyPublicKey(privateKey)); + NSData *message = [NSData dataWithBytes:"1234" length:4]; + NSMutableData *digest = [NSMutableData dataWithLength:di->output_size]; + ccdigest(di, message.length, message.bytes, digest.mutableBytes); + + // Verify algorithm's availability + ok(SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, algorithm), "algorithm %@ available on key %@", algorithm, privateKey); + ok(SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, digestAlgorithm), "algorithm %@ available on key %@", digestAlgorithm, privateKey); + + // Calculate signature of the message using SecKey + error = nil; + NSData *signature = CFBridgingRelease(SecKeyCreateSignature(privateKey, algorithm, (CFDataRef)message, (void *)&error)); + ok(signature != nil, "sign message with algorithm %@: error %@", algorithm, error); + + // Verify signature of the message using SecKey + error = nil; + Boolean verified = SecKeyVerifySignature((SecKeyRef)publicKey, algorithm, (CFDataRef)message, (CFDataRef)signature, (void *)&error); + ok(verified, "signature verified for algorithm %@: error %@", algorithm, error); + + // Calculate signature of the digest using SecKey + error = nil; + signature = CFBridgingRelease(SecKeyCreateSignature(privateKey, digestAlgorithm, (CFDataRef)digest, (void *)&error)); + ok(signature != nil, "sign digest with algorithm %@: error %@", digestAlgorithm, error); + + // Verify signature of the digest using CC + NSData *pubData = CFBridgingRelease(SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, (void *)&error)); + ok(pubData != nil, "export public key: error %@", error); + cc_size n = ccrsa_import_pub_n(pubData.length, pubData.bytes); + ccrsa_pub_ctx_decl(ccn_sizeof_n(n), ccpub); + ccrsa_ctx_n(ccpub) = n; + int err = ccrsa_import_pub(ccpub, pubData.length, pubData.bytes); + is(err, 0, "ccrsa_import_pub(key=%@) failed", publicKey); + + bool valid = false; + err = ccrsa_verify_pss(ccpub, di, di, di->output_size, digest.bytes, signature.length, signature.bytes, di->output_size, &valid); + is(err, 0, "ccrsa_verify_pss(%@) failed", algorithm); + ok(valid, "ccrsa verify signature (alg %@)", algorithm); + + // Calculate signature of the digest using CC + error = nil; + NSData *privData = CFBridgingRelease(SecKeyCopyExternalRepresentation(privateKey, (void *)&error)); + ok(privData != nil, "export private key: error %@", error); + n = ccrsa_import_priv_n(privData.length, privData.bytes); + ccrsa_full_ctx_decl(ccn_sizeof_n(n), ccpriv); + ccrsa_ctx_n(ccpriv) = n; + err = ccrsa_import_priv(ccpriv, privData.length, privData.bytes); + is(err, 0, "ccrsa_import_priv(key=%@) failed", privateKey); + + NSMutableData *ccSig = [NSMutableData dataWithLength:SecKeyGetBlockSize(privateKey)]; + size_t sigSize = ccSig.length; + err = ccrsa_sign_pss(ccpriv, di, di, di->output_size, ccrng(NULL), digest.length, digest.bytes, &sigSize, ccSig.mutableBytes); + is(err, 0, "ccrsa_sign_pss(%@) failed", digestAlgorithm); + is(sigSize, ccSig.length, "unexpected signature size for algorithm %@", digestAlgorithm); + + // Verify signature of the digest using SecKey + error = nil; + verified = SecKeyVerifySignature((SecKeyRef)publicKey, digestAlgorithm, (CFDataRef)digest, (CFDataRef)ccSig, (void *)&error); + ok(verified, "signature verified for algorithm %@: error %@", digestAlgorithm, error); +} +static const int TestCountPSSSignRun = 14; + +static void test_pss_sign() { + NSError *error; + NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @1024}; + + error = nil; + id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error)); + ok(privateKey != nil, "generate private key (error %@)", error); + + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA1, kSecKeyAlgorithmRSASignatureDigestPSSSHA1, ccsha1_di()); + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA224, kSecKeyAlgorithmRSASignatureDigestPSSSHA224, ccsha224_di()); + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA256, kSecKeyAlgorithmRSASignatureDigestPSSSHA256, ccsha256_di()); + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA384, kSecKeyAlgorithmRSASignatureDigestPSSSHA384, ccsha384_di()); + + // RSASSA-PSS requires hlen + slen + 2 size modulus, so it requires at least 1040bit keys, and should not be available for 1024b keys. + ok(!SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, kSecKeyAlgorithmRSASignatureDigestPSSSHA512)); + ok(!SecKeyIsAlgorithmSupported((SecKeyRef)privateKey, kSecKeyOperationTypeSign, kSecKeyAlgorithmRSASignatureMessagePSSSHA512)); + + error = nil; + params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048}; + privateKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)params, (void *)&error)); + ok(privateKey != nil, "generate private key (error %@)", error); + + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA1, kSecKeyAlgorithmRSASignatureDigestPSSSHA1, ccsha1_di()); + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA224, kSecKeyAlgorithmRSASignatureDigestPSSSHA224, ccsha224_di()); + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA256, kSecKeyAlgorithmRSASignatureDigestPSSSHA256, ccsha256_di()); + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA384, kSecKeyAlgorithmRSASignatureDigestPSSSHA384, ccsha384_di()); + test_pss_sign_run((__bridge SecKeyRef)privateKey, kSecKeyAlgorithmRSASignatureMessagePSSSHA512, kSecKeyAlgorithmRSASignatureDigestPSSSHA512, ccsha512_di()); +} +static const int TestCountPSSSign = 1 + TestCountPSSSignRun * 4 + 2 + 1 + TestCountPSSSignRun * 5; + static void test_bad_input(NSInteger keySizeInBits, NSInteger inputSize, SecKeyAlgorithm algorithm) { NSError *error; NSDictionary *params = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @(keySizeInBits)}; @@ -231,6 +332,7 @@ static const int TestCountBadSignature = 12; static const int TestCount = TestCountEncryption + +TestCountPSSSign + TestCountBadInputSize + TestCountBadSignature; @@ -239,6 +341,7 @@ int si_44_seckey_rsa(int argc, char *const *argv) { @autoreleasepool { test_encryption(); + test_pss_sign(); test_bad_input_size(); test_bad_signature(); }