void 
SecKeyGeneratePairAsync(CFDictionaryRef parametersWhichMightBeMutiable, dispatch_queue_t deliveryQueue, 
						SecKeyGeneratePairBlock result)
{
	CFDictionaryRef parameters = CFDictionaryCreateCopy(NULL, parametersWhichMightBeMutiable);
	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
		SecKeyRef publicKey = NULL;
		SecKeyRef privateKey = NULL;
		OSStatus status = SecKeyGeneratePair(parameters, &publicKey, &privateKey);
		dispatch_async(deliveryQueue, ^{
			CFErrorRef error = NULL;
			if (noErr != status) {
				error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, status, NULL);
			}
			result(publicKey, privateKey, error);
			if (error) {
				CFRelease(error);
			}
			if (publicKey) {
				CFRelease(publicKey);
			}
			if (privateKey) {
				CFRelease(privateKey);
			}
			CFRelease(parameters);
		});
	});
static OSStatus GenerateRSAKeyPair(
    SecKeychainRef keychain,
    CFStringRef keyLabel,
    int keySizeValue,
    Boolean *extractable,
    SecKeyRef *publicKeyRef,
    SecKeyRef *privateKeyRef)
{
    OSStatus status;
	CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue);

	// create a SecAccessRef to set up the initial access control settings for this key
	// (this step is optional; if omitted, the creating application has access to the key)
	// note: the access descriptor should be the same string as will be used for the item's label,
	// since it's the string that is displayed by the access confirmation dialog to describe the item.
	SecAccessRef access = NULL;
	status = SecAccessCreate(keyLabel, NULL, &access);

	// create a dictionary of parameters describing the key we want to create
	CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0,
                                                              &kCFTypeDictionaryKeyCallBacks,
                                                              &kCFTypeDictionaryValueCallBacks);
/*
 From the header doc for SecKeyGeneratePair (seems to be incomplete...):
    * kSecAttrLabel default NULL
    * kSecAttrIsPermanent if this key is present and has a Boolean
      value of true, the key or key pair will be added to the default
      keychain.
    * kSecAttrApplicationTag default NULL
    * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits
    * kSecAttrCanEncrypt default false for private keys, true for public keys
    * kSecAttrCanDecrypt default true for private keys, false for public keys
    * kSecAttrCanDerive default true
    * kSecAttrCanSign default true for private keys, false for public keys
    * kSecAttrCanVerify default false for private keys, true for public keys
    * kSecAttrCanWrap default false for private keys, true for public keys
    * kSecAttrCanUnwrap default true for private keys, false for public keys
*/
	CFDictionaryAddValue( params, kSecUseKeychain, keychain );
	CFDictionaryAddValue( params, kSecAttrAccess, access );
	CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA );
    CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); CFReleaseNull(keySize);
    CFDictionaryAddValue( params, kSecAttrIsPermanent, kCFBooleanTrue );

	if (extractable)
        CFDictionaryAddValue( params, kSecAttrIsExtractable, (*extractable) ? kCFBooleanTrue : kCFBooleanFalse );
	if (keyLabel)
		CFDictionaryAddValue( params, kSecAttrLabel, keyLabel );

    // generate the key
    status = SecKeyGeneratePair(params, publicKeyRef, privateKeyRef);
    ok_status(status, "%s: SecKeyGeneratePair", testName);

	if (params) CFRelease(params);
	if (access) CFRelease(access);

	return status;
}
Пример #3
0
extern "C" int32_t AppleCryptoNative_RsaGenerateKey(
    int32_t keySizeBits, SecKeychainRef tempKeychain, SecKeyRef* pPublicKey, SecKeyRef* pPrivateKey, int32_t* pOSStatus)
{
    if (pPublicKey != nullptr)
        *pPublicKey = nullptr;
    if (pPrivateKey != nullptr)
        *pPrivateKey = nullptr;

    if (pPublicKey == nullptr || pPrivateKey == nullptr || pOSStatus == nullptr)
        return kErrorBadInput;
    if (keySizeBits < 384 || keySizeBits > 16384)
        return -2;

    CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(nullptr, 2, &kCFTypeDictionaryKeyCallBacks, nullptr);

    CFNumberRef cfKeySizeValue = CFNumberCreate(nullptr, kCFNumberIntType, &keySizeBits);
    OSStatus status;

    if (attributes != nullptr && cfKeySizeValue != nullptr)
    {
        CFDictionaryAddValue(attributes, kSecAttrKeyType, kSecAttrKeyTypeRSA);
        CFDictionaryAddValue(attributes, kSecAttrKeySizeInBits, cfKeySizeValue);
        CFDictionaryAddValue(attributes, kSecUseKeychain, tempKeychain);

        status = SecKeyGeneratePair(attributes, pPublicKey, pPrivateKey);

        if (status == noErr)
        {
            status = ExportImportKey(pPublicKey, kSecItemTypePublicKey);
        }

        if (status == noErr)
        {
            status = ExportImportKey(pPrivateKey, kSecItemTypePrivateKey);
        }
    }
    else
    {
        status = errSecAllocate;
    }

    if (attributes != nullptr)
        CFRelease(attributes);
    if (cfKeySizeValue != nullptr)
        CFRelease(cfKeySizeValue);

    *pOSStatus = status;
    return status == noErr;
}
Пример #4
0
static int				/* O - 1 on success, 0 on failure */
make_certificate(cupsd_client_t *con)	/* I - Client connection */
{
#    ifdef HAVE_SECGENERATESELFSIGNEDCERTIFICATE
  int			status = 0;	/* Return status */
  OSStatus		err;		/* Error code (if any) */
#  if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
  char			localname[1024];/* Local hostname */
#  endif /* HAVE_DNSSD || HAVE_AVAHI */
  const char		*servername;	/* Name of server in cert */
  CFStringRef		cfservername = NULL;
					/* CF string for server name */
  SecIdentityRef	ident = NULL;	/* Identity */
  SecKeyRef		publicKey = NULL,
					/* Public key */
			privateKey = NULL;
					/* Private key */
  CFMutableDictionaryRef keyParams = NULL;
					/* Key generation parameters */


  cupsdLogMessage(CUPSD_LOG_INFO,
                  "Generating SSL server key and certificate.");

#  if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
  if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
  {
    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
    servername = localname;
  }
  else
#  endif /* HAVE_DNSSD || HAVE_AVAHI */
  servername = con->servername;

  cfservername = CFStringCreateWithCString(kCFAllocatorDefault, servername,
                                           kCFStringEncodingUTF8);
  if (!cfservername)
    goto cleanup;

 /*
  * Create a public/private key pair...
  */

  keyParams = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
					&kCFTypeDictionaryKeyCallBacks,
					&kCFTypeDictionaryValueCallBacks);
  if (!keyParams)
    goto cleanup;

  CFDictionaryAddValue(keyParams, kSecAttrKeyType, kSecAttrKeyTypeRSA);
  CFDictionaryAddValue(keyParams, kSecAttrKeySizeInBits, CFSTR("2048"));
  CFDictionaryAddValue(keyParams, kSecAttrLabel,
                       CFSTR("CUPS Self-Signed Certificate"));

  err = SecKeyGeneratePair(keyParams, &publicKey, &privateKey);
  if (err != noErr)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG, "SecKeyGeneratePair returned %ld.",
                    (long)err);
    goto cleanup;
  }

 /*
  * Create a self-signed certificate using the public/private key pair...
  */

  CFIndex	usageInt = kSecKeyUsageAll;
  CFNumberRef	usage = CFNumberCreate(alloc, kCFNumberCFIndexType, &usageInt);
  CFDictionaryRef certParams = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                   kSecCSRBasicContraintsPathLen, CFINT(0),
                                   kSecSubjectAltName, cfservername,
                                   kSecCertificateKeyUsage, usage,
                                   NULL, NULL);
  CFRelease(usage);
        
  const void	*ca_o[] = { kSecOidOrganization, CFSTR("") };
  const void	*ca_cn[] = { kSecOidCommonName, cfservername };
  CFArrayRef	ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL);
  CFArrayRef	ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL);
  const void	*ca_dn_array[2];

  ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn,
                                 1, NULL);
  ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn,
                                 1, NULL);

  CFArrayRef	subject = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2,
                                        NULL);
  SecCertificateRef cert = SecGenerateSelfSignedCertificate(subject, certParams,
                                                            publicKey,
                                                            privateKey);
  CFRelease(subject);
  CFRelease(certParams);

  if (!cert)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG, "SecGenerateSelfSignedCertificate failed.");
    goto cleanup;
  }

  ident = SecIdentityCreate(kCFAllocatorDefault, cert, privateKey);

  if (ident)
    cupsdLogMessage(CUPSD_LOG_INFO,
                    "Created SSL server certificate file \"%s\".",
		    ServerCertificate);

 /*
  * Cleanup and return...
  */

cleanup:

  if (cfservername)
    CFRelease(cfservername);

  if (keyParams)
    CFRelease(keyParams);

  if (ident)
    CFRelease(ident);

  if (cert)
    CFRelease(cert);

  if (publicKey)
    CFRelease(publicKey);

  if (privateKey)
    CFRelease(publicKey);

  if (!status)
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to create SSL server key and certificate.");

  return (status);

#    else /* !HAVE_SECGENERATESELFSIGNEDCERTIFICATE */
  int		pid,			/* Process ID of command */
		status;			/* Status of command */
  char		command[1024],		/* Command */
		*argv[4],		/* Command-line arguments */
		*envp[MAX_ENV + 1],	/* Environment variables */
		keychain[1024],		/* Keychain argument */
		infofile[1024],		/* Type-in information for cert */
#      if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
		localname[1024],	/* Local hostname */
#      endif /* HAVE_DNSSD || HAVE_AVAHI */
		*servername;		/* Name of server in cert */
  cups_file_t	*fp;			/* Seed/info file */
  int		infofd;			/* Info file descriptor */


#      if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
  if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
  {
    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
    servername = localname;
  }
  else
#      endif /* HAVE_DNSSD || HAVE_AVAHI */
    servername = con->servername;

 /*
  * Run the "certtool" command to generate a self-signed certificate...
  */

  if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command)))
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "No SSL certificate and certtool command not found.");
    return (0);
  }

 /*
  * Create a file with the certificate information fields...
  *
  * Note: This assumes that the default questions are asked by the certtool
  * command...
  */

  if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to create certificate information file %s - %s",
                    infofile, strerror(errno));
    return (0);
  }

  cupsFilePrintf(fp,
                 "%s\n"			/* Enter key and certificate label */
                 "r\n"			/* Generate RSA key pair */
                 "2048\n"		/* Key size in bits */
                 "y\n"			/* OK (y = yes) */
                 "b\n"			/* Usage (b=signing/encryption) */
                 "s\n"			/* Sign with SHA1 */
                 "y\n"			/* OK (y = yes) */
                 "%s\n"			/* Common name */
                 "\n"			/* Country (default) */
                 "\n"			/* Organization (default) */
                 "\n"			/* Organizational unit (default) */
                 "\n"			/* State/Province (default) */
                 "%s\n"			/* Email address */
                 "y\n",			/* OK (y = yes) */
        	 servername, servername, ServerAdmin);
  cupsFileClose(fp);

  cupsdLogMessage(CUPSD_LOG_INFO,
                  "Generating SSL server key and certificate.");

  snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate);

  argv[0] = "certtool";
  argv[1] = "c";
  argv[2] = keychain;
  argv[3] = NULL;

  cupsdLoadEnv(envp, MAX_ENV);

  infofd = open(infofile, O_RDONLY);

  if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
                         NULL, &pid))
  {
    close(infofd);
    unlink(infofile);
    return (0);
  }

  close(infofd);
  unlink(infofile);

  while (waitpid(pid, &status, 0) < 0)
    if (errno != EINTR)
    {
      status = 1;
      break;
    }

  cupsdFinishProcess(pid, command, sizeof(command), NULL);

  if (status)
  {
    if (WIFEXITED(status))
      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Unable to create SSL server key and certificate - "
		      "the certtool command stopped with status %d.",
	              WEXITSTATUS(status));
    else
      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Unable to create SSL server key and certificate - "
		      "the certtool command crashed on signal %d.",
	              WTERMSIG(status));
  }
  else
  {
    cupsdLogMessage(CUPSD_LOG_INFO,
                    "Created SSL server certificate file \"%s\".",
		    ServerCertificate);
  }

  return (!status);
#    endif /* HAVE_SECGENERATESELFSIGNEDCERTIFICATE */
}
static void testkeywrap(unsigned long keySizeInBits, CFTypeRef alg)
{
    SecKeyRef pubKey = NULL, privKey = NULL;
    size_t keySizeInBytes = (keySizeInBits + 7) / 8;
    CFNumberRef kzib;
    int32_t keysz32 = (int32_t)keySizeInBits;

    CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault);
    CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID);
    CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
    CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);

    CFReleaseNull(ourUUID);
    CFReleaseNull(uuidString);

    CFStringAppend(publicName, CFSTR("-Public-41"));
    CFStringAppend(privateName, CFSTR("-Private-41"));

    CFDictionaryRef pubd = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
                                                        kSecAttrLabel, publicName,
                                                        NULL);
    CFDictionaryRef privd = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
                                                         kSecAttrLabel, privateName,
                                                         NULL);

    CFReleaseNull(publicName);
    CFReleaseNull(privateName);

    kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
    CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
                                                       kSecAttrKeyType, kSecAttrKeyTypeEC,
                                                       kSecAttrKeySizeInBits, kzib,
                                                       kSecAttrIsPermanent, kCFBooleanFalse,
                                                       kSecPublicKeyAttrs, pubd,
                                                       kSecPrivateKeyAttrs, privd,
                                                       NULL);
    CFReleaseNull(pubd);
    CFReleaseNull(privd);
    CFReleaseNull(kzib);

    OSStatus status;
    ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
              "Generate %ld bit (%ld byte) persistent RSA keypair (status = %d)",
              keySizeInBits, keySizeInBytes, (int)status);
    CFReleaseNull(kgp);

    CFErrorRef localError;

    CFDataRef secret = CFDataCreate(NULL, (void *)"0123456789012345", 16);
    ok(secret, "secret");

    CFDataRef fp = CFDataCreate(NULL, (void *)"01234567890123456789", 20);
    ok(fp, "fingerprint");


    int8_t sym_alg_data = 8;
    CFNumberRef symalg = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg_data);
    CFDictionaryRef param = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
                                                         _kSecKeyWrapPGPWrapAlg, alg,
                                                         _kSecKeyWrapPGPSymAlg, symalg,
                                                         _kSecKeyWrapPGPFingerprint, fp,
                                                         NULL);

    CFDataRef wrapped = _SecKeyCopyWrapKey(pubKey, kSecKeyWrapPublicKeyPGP, secret, param, NULL, &localError);
    ok(wrapped, "wrap key: %@", localError);

    CFDataRef unwrapped = _SecKeyCopyUnwrapKey(privKey, kSecKeyWrapPublicKeyPGP, wrapped, param, NULL, &localError);
    ok(unwrapped, "unwrap key: %@", localError);

    CFReleaseNull(symalg);

    ok(CFEqual(unwrapped, secret), "keys still same");

    CFReleaseNull(fp);
    CFReleaseNull(secret);
    CFReleaseNull(unwrapped);
    CFReleaseNull(wrapped);
    CFReleaseNull(param);
    CFReleaseNull(privKey);
    CFReleaseNull(pubKey);
}
static void testkeygen2(size_t keySizeInBits) {
	SecKeyRef pubKey = NULL, privKey = NULL;
	size_t keySizeInBytes = (keySizeInBits + 7) / 8;
	CFNumberRef kzib;
    int32_t keysz32 = (int32_t)keySizeInBits;

    CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault);
    CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID);
    CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);
    CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString);

    CFReleaseNull(ourUUID);
    CFReleaseNull(uuidString);

    CFStringAppend(publicName, CFSTR("-Public-41"));
    CFStringAppend(privateName, CFSTR("-Private-41"));

    CFMutableDictionaryRef pubd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault,
                                                                          kSecAttrLabel, publicName,
                                                                          NULL);
    CFMutableDictionaryRef privd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault,
                                                                           kSecAttrLabel, privateName,
                                                                           NULL);

	kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
    CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
                                                       kSecAttrKeyType, kSecAttrKeyTypeEC,
                                                       kSecAttrKeySizeInBits, kzib,
                                                       kSecAttrIsPermanent, kCFBooleanTrue,
                                                       kSecPublicKeyAttrs, pubd,
                                                       kSecPrivateKeyAttrs, privd,
                                                       NULL);

    CFReleaseNull(kzib);

	OSStatus status;
	ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
              "Generate %ld bit (%ld byte) persistent RSA keypair",
              keySizeInBits, keySizeInBytes);

    CFReleaseNull(kgp);

SKIP: {
    skip("keygen failed", 8, status == errSecSuccess);
    ok(pubKey, "pubkey returned");
    ok(privKey, "privKey returned");
    is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
    is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");

    SecKeyRef pubKey2, privKey2;
    CFDictionaryAddValue(pubd, kSecClass, kSecClassKey);
    CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue);
    CFDictionaryAddValue(privd, kSecClass, kSecClassKey);
    CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue);
    CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue);
    ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2),
              "retrieve pub key by label");
    ok(pubKey2, "got valid object");
    ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2),
              "retrieve priv key by label and kSecAttrCanSign");
    ok(privKey2, "got valid object");

    /* Sign something. */
    uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
    size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize);
    uint8_t sig[sigLen];
    ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1,
                            something, sizeof(something), sig, &sigLen), "sign something");
    ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1,
                              something, sizeof(something), sig, sigLen), "verify sig on something");

    /* Cleanup. */
    CFReleaseNull(pubKey2);
    CFReleaseNull(privKey2);
}

    /* delete from keychain - note: do it before releasing publicName and privateName
       because pubd and privd have no retain/release callbacks */
    ok_status(SecItemDelete(pubd), "delete generated pub key");
    ok_status(SecItemDelete(privd), "delete generated priv key");

	/* Cleanup. */
	CFReleaseNull(pubKey);
	CFReleaseNull(privKey);

    CFReleaseNull(publicName);
    CFReleaseNull(privateName);

	CFReleaseNull(pubd);
	CFReleaseNull(privd);
}
static void testkeygen(size_t keySizeInBits) {
	SecKeyRef pubKey = NULL, privKey = NULL;
	size_t keySizeInBytes = (keySizeInBits + 7) / 8;
	CFNumberRef kzib;
    int32_t keysz32 = (int32_t)keySizeInBits;

	kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32);
	CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
	CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC);
	CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib);

	OSStatus status;
	ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey),
              "Generate %ld bit (%ld byte) EC keypair", keySizeInBits,
              keySizeInBytes);
	CFRelease(kzib);
	CFRelease(kgp);

SKIP: {
    skip("keygen failed", 8, status == errSecSuccess);
    ok(pubKey, "pubkey returned");
    ok(privKey, "privKey returned");
    is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok");
    is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok");

    /* Sign something. */
    uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
    uint8_t sig[8+2*keySizeInBytes];
    size_t sigLen = sizeof(sig);
    ok_status(SecKeyRawSign(privKey, kSecPaddingNone,
                            something, sizeof(something), sig, &sigLen), "sign something");
    ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone,
                              something, sizeof(something), sig, sigLen), "verify sig on something");

    testdigestandsign(privKey, pubKey);

    const void *privkeys[] = {
        kSecValueRef
    };
    const void *privvalues[] = {
        privKey
    };
    CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues,
                                                  array_size(privkeys), NULL, NULL);
    ok_status(SecItemAdd(privitem, NULL), "add private key");
    ok_status(SecItemDelete(privitem), "delete public key");
    CFReleaseNull(privitem);

    const void *pubkeys[] = {
        kSecValueRef
    };
    const void *pubvalues[] = {
        pubKey
    };
    CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues,
                                                 array_size(pubkeys), NULL, NULL);
    ok_status(SecItemAdd(pubitem, NULL), "add public key");
    ok_status(SecItemDelete(pubitem), "delete public key");
    CFReleaseNull(pubitem);

    /* Cleanup. */
    CFReleaseNull(pubKey);
    CFReleaseNull(privKey);
}
}
Пример #8
0
static void tests(void)
{
    SecKeyRef phone_publicKey = NULL, phone_privateKey = NULL;
    SecKeyRef ca_publicKey = NULL, ca_privateKey = NULL;

    int keysize = 2048;
    CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keysize);
    const void *keygen_keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits };
    const void *keygen_vals[] = { kSecAttrKeyTypeRSA, key_size_num };
    CFDictionaryRef parameters = CFDictionaryCreate(kCFAllocatorDefault,
        keygen_keys, keygen_vals, array_size(keygen_vals),
        &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
    CFReleaseNull(key_size_num);

    CFMutableDictionaryRef subject_alt_names = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(subject_alt_names, CFSTR("dnsname"), CFSTR("xey.nl"));

    int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment;
    CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage);

    CFMutableDictionaryRef random_extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    const void *key[] = { kSecCSRChallengePassword, kSecSubjectAltName, kSecCertificateKeyUsage, kSecCertificateExtensions };
    const void *val[] = { CFSTR("magic"), subject_alt_names, key_usage_num, random_extensions };
    CFDictionaryRef csr_parameters = CFDictionaryCreate(kCFAllocatorDefault,
        key, val, array_size(key), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    SecATV cn_phone[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("My iPhone") }, {} };
    SecATV c[]  = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} };
    SecATV st[] = { { kSecOidStateProvinceName, SecASN1PrintableString, CFSTR("CA") }, {} };
    SecATV l[]  = { { kSecOidLocalityName, SecASN1PrintableString, CFSTR("Cupertino") }, {} };
    SecATV o[]  = { { CFSTR("2.5.4.10"), SecASN1PrintableString, CFSTR("Apple Inc.") }, {} };
    SecATV ou[] = { { kSecOidOrganizationalUnit, SecASN1PrintableString, CFSTR("iPhone") }, {} };

    SecRDN atvs_phone[] = { cn_phone, c, st, l, o, ou, NULL };

    ok_status(SecKeyGeneratePair(parameters, &phone_publicKey, &phone_privateKey), "generate key pair");
    ok_status(SecKeyGeneratePair(parameters, &ca_publicKey, &ca_privateKey), "generate key pair");

    int self_key_usage = kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign;
    CFNumberRef self_key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &self_key_usage);
    int path_len = 0;
    CFNumberRef path_len_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &path_len);
    const void *self_key[] = { kSecCertificateKeyUsage, kSecCSRBasicContraintsPathLen };
    const void *self_val[] = { self_key_usage_num, path_len_num };
    CFDictionaryRef self_signed_parameters = CFDictionaryCreate(kCFAllocatorDefault,
        self_key, self_val, array_size(self_key), NULL, NULL);

    const void * ca_o[] = { kSecOidOrganization, CFSTR("Apple Inc.") };
    const void * ca_cn[] = { kSecOidCommonName, CFSTR("Root CA") };
    CFArrayRef ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL);
    CFArrayRef ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL);
    const void *ca_dn_array[2];
    ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn, 1, NULL);
    ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn, 1, NULL);
    CFArrayRef ca_rdns = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2, NULL);

    SecCertificateRef ca_cert = SecGenerateSelfSignedCertificate(ca_rdns,
        self_signed_parameters, ca_publicKey, ca_privateKey);
	SecCertificateRef ca_cert_phone_key =
		SecGenerateSelfSignedCertificate(ca_rdns, self_signed_parameters, phone_publicKey, phone_privateKey);

	CFReleaseSafe(self_signed_parameters);
    CFReleaseSafe(self_key_usage_num);
    CFReleaseSafe(path_len_num);
    CFReleaseNull(ca_o_dn);
    CFReleaseNull(ca_cn_dn);
    CFReleaseNull(ca_dn_array[0]);
    CFReleaseNull(ca_dn_array[1]);
    CFReleaseNull(ca_rdns);

    isnt(ca_cert, NULL, "got back a cert");
    ok(SecCertificateIsSelfSignedCA(ca_cert), "cert is self-signed ca cert");
    isnt(ca_cert_phone_key, NULL, "got back a cert");
    ok(SecCertificateIsSelfSignedCA(ca_cert_phone_key), "cert is self-signed ca cert");
    CFDataRef data = SecCertificateCopyData(ca_cert);
    //write_data("/tmp/ca_cert.der", data);
    CFReleaseSafe(data);

    SecIdentityRef ca_identity = SecIdentityCreate(kCFAllocatorDefault, ca_cert, ca_privateKey);
	SecIdentityRef ca_identity_phone_key = SecIdentityCreate(kCFAllocatorDefault, ca_cert_phone_key, phone_privateKey);
    isnt(ca_identity, NULL, "got a identity");
    isnt(ca_identity_phone_key, NULL, "got a identity");
    CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity, 1, NULL, NULL);
    ok_status(SecItemAdd(dict, NULL), "add ca identity");
    CFReleaseSafe(dict);
#if TARGET_OS_IPHONE
    TODO: {
        todo("Adding a cert with the same issuer/serial but a different key should return something other than errSecDuplicateItem");
#else
    {
#endif
        dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity_phone_key, 1, NULL, NULL);
        is_status(errSecDuplicateItem, SecItemAdd(dict, NULL), "add ca identity");
        CFReleaseSafe(dict);
    }

    CFDataRef csr = SecGenerateCertificateRequestWithParameters(atvs_phone, NULL, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "got back a csr");
    CFReleaseNull(csr);

	//dict[kSecSubjectAltName, dict[ntPrincipalName, "*****@*****.**"]]
	CFStringRef nt_princ_name_val = CFSTR("*****@*****.**");
	CFStringRef nt_princ_name_key = CFSTR("ntPrincipalName");
	CFDictionaryRef nt_princ = CFDictionaryCreate(NULL, (const void **)&nt_princ_name_key, (const void **)&nt_princ_name_val, 1, NULL, NULL);
	CFDictionaryRef params = CFDictionaryCreate(NULL, (const void **)&kSecSubjectAltName, (const void **)&nt_princ, 1, NULL, NULL);

    csr = SecGenerateCertificateRequestWithParameters(atvs_phone, params, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "got back a csr");
	//write_data("/var/tmp/csr-nt-princ", csr);
    CFReleaseNull(csr);
	CFReleaseNull(params);
	CFReleaseNull(nt_princ);

    csr = SecGenerateCertificateRequestWithParameters(atvs_phone, csr_parameters, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "csr w/ params");
    //write_data("/tmp/csr", csr);
    CFDataRef subject, extensions;
    CFStringRef challenge;
    ok(SecVerifyCertificateRequest(csr, NULL, &challenge, &subject, &extensions), "verify csr");
    CFReleaseNull(csr);

    uint8_t serialno_byte = 42;
    CFDataRef serialno = CFDataCreate(kCFAllocatorDefault, &serialno_byte, sizeof(serialno_byte));
    SecCertificateRef cert = SecIdentitySignCertificate(ca_identity, serialno,
        phone_publicKey, subject, extensions);
    data = SecCertificateCopyData(cert);
    //write_data("/tmp/iphone_cert.der", data);
    CFReleaseNull(data);
    CFReleaseNull(subject);
    CFReleaseNull(extensions);
    CFReleaseNull(challenge);

    const void * email[] = { CFSTR("1.2.840.113549.1.9.1"), CFSTR("*****@*****.**") };
    const void * cn[] = { CFSTR("2.5.4.3"), CFSTR("S/MIME Baby") };
    CFArrayRef email_dn = CFArrayCreate(kCFAllocatorDefault, email, 2, NULL);
    CFArrayRef cn_dn = CFArrayCreate(kCFAllocatorDefault, cn, 2, NULL);
    const void *dn_array[2];
    dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&email_dn, 1, NULL);
    dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&cn_dn, 1, NULL);
    CFArrayRef rdns = CFArrayCreate(kCFAllocatorDefault, dn_array, 2, NULL);
    CFDictionarySetValue(subject_alt_names, CFSTR("rfc822name"), CFSTR("*****@*****.**"));

    uint8_t random_extension_data[] = { 0xde, 0xad, 0xbe, 0xef };
    CFDataRef random_extension_value = CFDataCreate(kCFAllocatorDefault, random_extension_data, sizeof(random_extension_data));
    CFDictionarySetValue(random_extensions, CFSTR("1.2.840.113635.100.6.1.2"), random_extension_value);  // APPLE_FDR_ACCESS_OID
    CFDictionarySetValue(random_extensions, CFSTR("1.2.840.113635.100.6.1.3"), CFSTR("that guy"));  // APPLE_FDR_CLIENT_IDENTIFIER_OID
    CFReleaseNull(random_extension_value);

    csr = SecGenerateCertificateRequest(rdns, csr_parameters, phone_publicKey, phone_privateKey);
    isnt(csr, NULL, "csr w/ params");
    //write_data("/tmp/csr_neu", csr);
    CFReleaseNull(csr);
    CFReleaseNull(subject_alt_names);
    CFDictionaryRemoveAllValues(random_extensions);

#if TARGET_OS_IPHONE
    CFDataRef scep_request = SecSCEPGenerateCertificateRequest(rdns,
        csr_parameters, phone_publicKey, phone_privateKey, NULL, ca_cert);
    isnt(scep_request, NULL, "got scep blob");
    //write_data("/tmp/scep_request.der", scep_request);
#endif

    CFReleaseNull(email_dn);
    CFReleaseNull(cn_dn);
    CFReleaseNull(dn_array[0]);
    CFReleaseNull(dn_array[1]);
    CFReleaseNull(rdns);

#if TARGET_OS_IPHONE
    CFDataRef scep_reply = SecSCEPCertifyRequest(scep_request, ca_identity, serialno, false);
    isnt(scep_reply, NULL, "produced scep reply");
    //write_data("/tmp/scep_reply.der", scep_reply);

    CFArrayRef issued_certs = NULL;
    ok(issued_certs = SecSCEPVerifyReply(scep_request, scep_reply, ca_cert, NULL), "verify scep reply");

    // take the issued cert and CA cert and pretend it's a RA/CA couple
    CFMutableArrayRef scep_certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, issued_certs);
    CFArrayAppendValue(scep_certs, ca_cert);
    SecCertificateRef ca_certificate = NULL, ra_signing_certificate = NULL, ra_encryption_certificate = NULL;

    ok_status(SecSCEPValidateCACertMessage(scep_certs, NULL,
        &ca_certificate, &ra_signing_certificate,
        &ra_encryption_certificate), "pull apart array again");
    ok(CFEqual(ca_cert, ca_certificate), "found ca");
    ok(CFArrayContainsValue(issued_certs, CFRangeMake(0, CFArrayGetCount(issued_certs)), ra_signing_certificate), "found ra");
    ok(!ra_encryption_certificate, "no separate encryption cert");

    CFReleaseSafe(ca_certificate);
    CFReleaseSafe(ra_signing_certificate);
    CFReleaseSafe(scep_certs);

    CFReleaseSafe(scep_request);
    CFReleaseSafe(scep_reply);
    CFReleaseSafe(issued_certs);
#endif

    // cleanups
    dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity, 1, NULL, NULL);
    ok_status(SecItemDelete(dict), "delete ca identity");
	CFReleaseSafe(dict);
    dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&phone_privateKey, 1, NULL, NULL);
    ok_status(SecItemDelete(dict), "delete phone private key");
	CFReleaseSafe(dict);

    CFReleaseSafe(serialno);

    CFReleaseSafe(cert);
    CFReleaseSafe(ca_identity);
    CFReleaseSafe(ca_cert);
	CFReleaseSafe(ca_identity_phone_key);
	CFReleaseSafe(ca_cert_phone_key);
    CFReleaseSafe(csr_parameters);
    CFReleaseSafe(random_extensions);
    CFReleaseSafe(parameters);
    CFReleaseSafe(ca_publicKey);
    CFReleaseSafe(ca_privateKey);
    CFReleaseSafe(phone_publicKey);
    CFReleaseSafe(phone_privateKey);
}

static void test_ec_csr(void) {
    SecKeyRef ecPublicKey = NULL, ecPrivateKey = NULL;

    int keysize = 256;
    CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keysize);

    const void *keyParamsKeys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits };
    const void *keyParamsValues[] = { kSecAttrKeyTypeECSECPrimeRandom,  key_size_num};
    CFDictionaryRef keyParameters = CFDictionaryCreate(NULL, keyParamsKeys, keyParamsValues, 2,
                                                       &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    ok_status(SecKeyGeneratePair(keyParameters, &ecPublicKey, &ecPrivateKey),
              "unable to generate EC key");

    SecATV cn_phone[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("My iPhone") }, {} };
    SecATV c[]  = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} };
    SecATV st[] = { { kSecOidStateProvinceName, SecASN1PrintableString, CFSTR("CA") }, {} };
    SecATV l[]  = { { kSecOidLocalityName, SecASN1PrintableString, CFSTR("Cupertino") }, {} };
    SecATV o[]  = { { CFSTR("2.5.4.10"), SecASN1PrintableString, CFSTR("Apple Inc.") }, {} };
    SecATV ou[] = { { kSecOidOrganizationalUnit, SecASN1PrintableString, CFSTR("iPhone") }, {} };

    SecRDN atvs_phone[] = { cn_phone, c, st, l, o, ou, NULL };

    CFMutableDictionaryRef subject_alt_names = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(subject_alt_names, CFSTR("dnsname"), CFSTR("xey.nl"));

    int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment;
    CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage);

    CFMutableDictionaryRef random_extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    const void *key[] = { kSecCSRChallengePassword, kSecSubjectAltName, kSecCertificateKeyUsage, kSecCertificateExtensions };
    const void *val[] = { CFSTR("magic"), subject_alt_names, key_usage_num, random_extensions };
    CFDictionaryRef csr_parameters = CFDictionaryCreate(kCFAllocatorDefault,
                                                        key, val, array_size(key), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);


    CFDataRef csr = SecGenerateCertificateRequestWithParameters(atvs_phone, csr_parameters, ecPublicKey, ecPrivateKey);
    isnt(csr, NULL, "csr w/ params");
    //write_data("/tmp/csr", csr);
    CFDataRef subject, extensions;
    CFStringRef challenge;
    ok(SecVerifyCertificateRequest(csr, NULL, &challenge, &subject, &extensions), "verify csr");

    CFReleaseNull(csr);
    CFReleaseNull(key_size_num);
    CFReleaseNull(keyParameters);
    CFReleaseNull(ecPublicKey);
    CFReleaseNull(ecPrivateKey);
    CFReleaseNull(subject_alt_names);
    CFReleaseNull(key_usage_num);
    CFReleaseNull(random_extensions);
    CFReleaseNull(csr_parameters);
    CFReleaseNull(subject);
    CFReleaseNull(extensions);
    CFReleaseNull(challenge);
}