1/* 2 * Copyright (c) 1999-2001,2005-2008,2010-2014 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 * sslKeychain.c - Apple Keychain routines 26 */ 27 28#include "ssl.h" 29#include "sslContext.h" 30#include "sslMemory.h" 31 32#include "sslCrypto.h" 33#include <Security/SecBase.h> 34#include <Security/SecCertificate.h> 35#include <Security/SecCertificatePriv.h> 36#include <Security/SecIdentity.h> 37#include <Security/SecPolicy.h> 38#include <Security/SecTrust.h> 39#include "utilities/SecCFRelease.h" 40 41#include "sslDebug.h" 42#include "sslKeychain.h" 43#include "sslUtils.h" 44#include <string.h> 45#include <assert.h> 46 47 48#include <Security/Security.h> 49#include <Security/SecKeyPriv.h> 50#include <AssertMacros.h> 51#include <tls_handshake.h> 52 53#if TARGET_OS_IPHONE 54#include <Security/oidsalg.h> 55#endif 56 57/* Private Key operations */ 58static 59SecAsn1Oid oidForSSLHash(SSL_HashAlgorithm hash) 60{ 61 switch (hash) { 62 case tls_hash_algorithm_SHA1: 63 return CSSMOID_SHA1WithRSA; 64 case tls_hash_algorithm_SHA256: 65 return CSSMOID_SHA256WithRSA; 66 case tls_hash_algorithm_SHA384: 67 return CSSMOID_SHA384WithRSA; 68 default: 69 break; 70 } 71 // Internal error 72 assert(0); 73 // This guarantee failure down the line 74 return CSSMOID_MD5WithRSA; 75} 76 77static 78int mySSLPrivKeyRSA_sign(void *key, tls_hash_algorithm hash, const uint8_t *plaintext, size_t plaintextLen, uint8_t *sig, size_t *sigLen) 79{ 80 SecKeyRef keyRef = key; 81 82 if(hash == tls_hash_algorithm_None) { 83 return SecKeyRawSign(keyRef, kSecPaddingPKCS1, plaintext, plaintextLen, sig, sigLen); 84 } else { 85 SecAsn1AlgId algId; 86 algId.algorithm = oidForSSLHash(hash); 87 return SecKeySignDigest(keyRef, &algId, plaintext, plaintextLen, sig, sigLen); 88 } 89} 90 91static 92int mySSLPrivKeyRSA_decrypt(void *key, const uint8_t *ciphertext, size_t ciphertextLen, uint8_t *plaintext, size_t *plaintextLen) 93{ 94 SecKeyRef keyRef = key; 95 96 return SecKeyDecrypt(keyRef, kSecPaddingPKCS1, ciphertext, ciphertextLen, plaintext, plaintextLen); 97} 98 99void sslFreePrivKey(tls_private_key_t *sslPrivKey) 100{ 101 assert(sslPrivKey); 102 103 if(*sslPrivKey) { 104 CFReleaseSafe(tls_private_key_get_context(*sslPrivKey)); 105 tls_private_key_destroy(*sslPrivKey); 106 *sslPrivKey = NULL; 107 } 108} 109 110OSStatus 111parseIncomingCerts( 112 SSLContext *ctx, 113 CFArrayRef certs, 114 SSLCertificate **destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ 115 tls_private_key_t *sslPrivKey) /* &ctx->signingPrivKeyRef, etc. */ 116{ 117 OSStatus ortn; 118 CFIndex ix, numCerts; 119 SecIdentityRef identity; 120 SSLCertificate *certChain = NULL; /* Retained */ 121 SecCertificateRef leafCert = NULL; /* Retained */ 122 SecKeyRef privKey = NULL; /* Retained */ 123 124 assert(ctx != NULL); 125 assert(destCertChain != NULL); /* though its referent may be NULL */ 126 assert(sslPrivKey != NULL); 127 128 if (certs == NULL) { 129 sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); 130 ortn = errSSLBadCert; 131 goto errOut; 132 } 133 numCerts = CFArrayGetCount(certs); 134 if (numCerts == 0) { 135 sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); 136 ortn = errSSLBadCert; 137 goto errOut; 138 } 139 140 certChain=sslMalloc(numCerts*sizeof(SSLCertificate)); 141 if (!certChain) { 142 ortn = errSecAllocate; 143 goto errOut; 144 } 145 146 /* 147 * Certs[0] is an SecIdentityRef from which we extract subject cert, 148 * privKey, pubKey. 149 * 150 * 1. ensure the first element is a SecIdentityRef. 151 */ 152 identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); 153 if (identity == NULL) { 154 sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); 155 ortn = errSecParam; 156 goto errOut; 157 } 158 if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { 159 sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); 160 ortn = errSecParam; 161 goto errOut; 162 } 163 164 /* 165 * 2. Extract cert, keys and convert to local format. 166 */ 167 ortn = SecIdentityCopyCertificate(identity, &leafCert); 168 if (ortn) { 169 sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); 170 goto errOut; 171 } 172 173 /* Fetch private key from identity */ 174 ortn = SecIdentityCopyPrivateKey(identity, &privKey); 175 if (ortn) { 176 sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", 177 (int)ortn); 178 goto errOut; 179 } 180 181 /* Convert the input array of SecIdentityRef at the start to an array of 182 all certificates. */ 183 184 certChain[0].derCert.data = (uint8_t *)SecCertificateGetBytePtr(leafCert); 185 certChain[0].derCert.length = SecCertificateGetLength(leafCert); 186 certChain[0].next = NULL; 187 188 for (ix = 1; ix < numCerts; ++ix) { 189 SecCertificateRef intermediate = 190 (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix); 191 if (intermediate == NULL) { 192 sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); 193 ortn = errSecParam; 194 goto errOut; 195 } 196 if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { 197 sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); 198 ortn = errSecParam; 199 goto errOut; 200 } 201 202 certChain[ix].derCert.data = (uint8_t *)SecCertificateGetBytePtr(intermediate); 203 certChain[ix].derCert.length = SecCertificateGetLength(intermediate); 204 certChain[ix].next = NULL; 205 certChain[ix-1].next = &certChain[ix]; 206 207 } 208 209 if(sslPrivKeyGetAlgorithmID(privKey)!=kSecRSAAlgorithmID) { 210 ortn = errSecParam; 211 goto errOut; 212 } 213 214 sslFreePrivKey(sslPrivKey); 215 *sslPrivKey = tls_private_key_rsa_create(privKey, SecKeyGetBlockSize(privKey), mySSLPrivKeyRSA_sign, mySSLPrivKeyRSA_decrypt); 216 if(*sslPrivKey) 217 ortn = errSecSuccess; 218 else 219 ortn = errSecAllocate; 220 221 /* SUCCESS */ 222errOut: 223 CFReleaseSafe(leafCert); 224 225 sslFree(*destCertChain); 226 227 if (ortn) { 228 free(certChain); 229 CFReleaseSafe(privKey); 230 *destCertChain = NULL; 231 } else { 232 *destCertChain = certChain; 233 } 234 235 return ortn; 236} 237