--- /dev/null
+/*
+ * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*******************************************************************
+ *
+ * SecPkcs12.h
+ *
+ * This module is an implementation of the logic required to create
+ * and parse PKCS12 "blobs", known as PFXs in PKCS12 lingo. The user
+ * of this module need not know anything about the details of
+ * PKCS12 PFX construction. All one needs to know at this level
+ * is that a PKCS12 PFX is a collection of the following items:
+ *
+ * -- Zero or more certificates
+ * -- Zero or more Certficate Revocation Lists (CRLs)
+ * -- Zero or more private keys. (If this number is zero, using this
+ * module is probably not what you want to do)
+ * -- Zero or more other opaque types, not understood or parsed
+ * by this module.
+ *
+ * Each individual component of a PFX contains zero or more
+ * attributes; commonly the only two such attributes used in
+ * the PKCS12 world are "FriendlyName", a Unicode string, and
+ * "LocalKeyId", an opaque data blob which serves solely to tie
+ * a specific cert to a specific key in the context of this specific
+ * PFX.
+ *
+ * Individual components of a PKCS12 PFX are typically encrypted with
+ * a key derived from a user-supplied passphrase. The entire PFX
+ * is protected with a MAC whose key is also derived from a user-
+ * supplied passphrase. Typically these two passphrases are identical
+ * but they don't have to be.
+ *
+ * There are a number of options and modes which, while described in
+ * the PKCS12 spec and provided for in the interface in this file,
+ * are rarely if ever used. The following is a description of the
+ * actual, typical, real-world use of this module.
+ *
+ * Decoding a PKCS12 blob
+ * ----------------------
+ *
+ * 1. App creates a SecPkcs12CoderRef via SecPkcs12CoderCreate().
+ *
+ * 2. App specifies supplies a (small) number of options such as
+ * passphrase(s) and SecKeychainRefs.
+ *
+ * 3. App calls SecPkcs12Decode(), providing the raw PKCS12 PFX
+ * blob which is to be decoded. This performs all of the actual
+ * decoding and decryption.
+ *
+ * 4. At this point the app optionally obtains the resulting
+ * components by a set of calls which return individual
+ * certs, CRLS, and keys.
+ *
+ * 5. Also, per the configuration performed in step 2, individual
+ * components (certs, keys) found in the PFX have been added
+ * to a specified keychain, rendering step 4 superfluous.
+ *
+ *
+ * Creating a PKCS12 blob
+ * ----------------------
+ *
+ * 1. App creates a SecPkcs12CoderRef via SecPkcs12CoderCreate().
+ *
+ * 2. App specifies supplies a (small) number of options such as
+ * passphrase(s).
+ *
+ * 3. App makes a set of calls which add individual components such
+ * as certs, CRLs, and private keys. A high-level call,
+ * SecPkcs12ExportKeychainItems(), allow the specification of
+ * all components to be exported at once.
+ *
+ * 4. App calls SecPkcs12Encode(), which does all of the required
+ * encryption and encoding. The result is an exportable PKCS12
+ * PFX blob.
+ */
+
+#ifndef _SEC_PKCS12_H_
+#define _SEC_PKCS12_H_
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Opaque handle for a PKCS12 encoder/decoder.
+ */
+typedef void *SecPkcs12CoderRef;
+
+#pragma mark --- SecPkcs12CoderRef create/destroy ---
+
+/*
+ * Basic SecPkcs12CoderRef create/destroy.
+ */
+OSStatus SecPkcs12CoderCreate(
+ SecPkcs12CoderRef *coder); // RETURNED
+
+/*
+ * Destroy object created in SecPkcs12CoderCreate.
+ */
+OSStatus SecPkcs12CoderRelease(
+ SecPkcs12CoderRef coder);
+
+#pragma mark --- High-level API ---
+
+/*
+ * Keychain associated with encode/decode.
+ * Client must call exactly one of { SecPkcs12SetKeychain(),
+ * SecPkcs12SetCspHandle() } for both encoding and decoding.
+ * If SecPkcs12SetCspHandle() is used, components which are
+ * obtained during decode are ephemeral (i.e., they are not
+ * stored anywhere and only have a lifetime which is the same as
+ * the lifetime of the SecPkcs12CoderRef).
+ */
+OSStatus SecPkcs12SetKeychain(
+ SecPkcs12CoderRef coder,
+ SecKeychainRef keychain);
+
+/*
+ * Required iff SecPkcs12SetKeychain() is not called.
+ */
+OSStatus SecPkcs12SetCspHandle(
+ SecPkcs12CoderRef coder,
+ CSSM_CSP_HANDLE cspHandle);
+
+
+/*
+ * PKCS12 allows for separate passphrases for encryption and for
+ * verification (via MAC). Typically, in the real world, one
+ * passphrase is used for both; we provide the means to set them
+ * separately.
+ *
+ * Passphrases can be specified directly as CFStringRefs, or as
+ * CSSM_KEYs which represent secure passphrases obtained by the
+ * SecurityServer. This latter method is preferred since the
+ * plaintext passphrase never appears in the app's address space.
+ * Passphrases expressed in this manner are referred to as
+ * PassKeys.
+ *
+ * If one passphrase is to be used for both encryption and
+ * verification, use one of these two function to set it.
+ */
+OSStatus SecPkcs12SetMACPassphrase(
+ SecPkcs12CoderRef coder,
+ CFStringRef passphrase);
+
+OSStatus SecPkcs12SetMACPassKey(
+ SecPkcs12CoderRef coder,
+ const CSSM_KEY *passKey);
+
+/*
+ * Specify separate passphrase for encrypt/decrypt.
+ */
+OSStatus SecPkcs12SetCryptPassphrase(
+ SecPkcs12CoderRef coder,
+ CFStringRef passphrase);
+
+OSStatus SecPkcs12SetCryptPassKey(
+ SecPkcs12CoderRef coder,
+ const CSSM_KEY *passKey);
+
+/*
+ * Prior to decoding a PFX, client can specify whether individual
+ * components (certificates, CRLs, and keys) get stored in the
+ * keychain specified via SecPkcs12SetKeychain().
+ */
+enum {
+ kSecImportCertificates = 0x0001,
+ kSecImportCRLs = 0x0002,
+ kSecImportKeys = 0x0004,
+};
+
+typedef UInt32 SecPkcs12ImportFlags;
+
+OSStatus SecPkcs12SetImportToKeychain(
+ SecPkcs12CoderRef coder,
+ SecPkcs12ImportFlags flags);
+
+OSStatus SecPkcs12GetImportToKeychain(
+ SecPkcs12CoderRef coder,
+ SecPkcs12ImportFlags *flags); // RETURNED
+
+/*
+ * Specify individual SecKeychainItemRef to export, prior to encoding.
+ * The items argument is a CFArray containing any number of each
+ * of the following SecKeychainItemRef objects:
+ *
+ * SecKeyRef
+ * SecCertificateRef
+ * ...and others, in the future.
+ */
+OSStatus SecPkcs12ExportKeychainItems(
+ SecPkcs12CoderRef coder,
+ CFArrayRef items);
+
+/*
+ * Specify additional optional imported private key attributes:
+ * -- a SecAccessRef; default is the default ACL. Passing NULL here
+ * results in private keys being created with no ACL.
+ * -- CSSM_KEYUSE; default is CSSM_KEYUSE_ANY.
+ * -- CSSM_KEYATTR_FLAGS; default is CSSM_KEYATTR_RETURN_REF |
+ * CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_SENSITIVE, plus
+ * CSSM_KEYATTR_PERMANENT if importing to a keychain
+ */
+OSStatus SecPkcs12SetAccess(
+ SecPkcs12CoderRef coder,
+ SecAccessRef access);
+
+OSStatus SecPkcs12SetKeyUsage(
+ SecPkcs12CoderRef coder,
+ CSSM_KEYUSE keyUsage);
+
+OSStatus SecPkcs12SetKeyAttrs(
+ SecPkcs12CoderRef coder,
+ CSSM_KEYATTR_FLAGS keyAttrs);
+
+/*
+ * Parse and decode.
+ */
+OSStatus SecPkcs12Decode(
+ SecPkcs12CoderRef coder,
+ CFDataRef pfx);
+
+/*
+ * This the final step to create an encoded PKCS12 PFX blob.
+ * This called after initial configuration of the SecPkcs12CoderRef,
+ * and either specifying items to export via either
+ * SecPkcs12ExportKeychainItems() or some number of SecPkcs12Add*
+ * function calls, described below.
+ *
+ * The result is a DER-encoded PFX in PKCS12 lingo.
+ */
+OSStatus SecPkcs12Encode(
+ SecPkcs12CoderRef coder,
+ CFDataRef *pfx); // RETURNED
+
+
+/*
+ * Opaque handle for optional attributes associated with any
+ * component of a SecPkcs12CoderRef.
+ *
+ * The use of SecPkcs12AttrsRefs is optional and in fact, in the real
+ * world, rare. Their appearance in this API is just for completeness
+ * and to allow access to all "legal" PKCS12 options.
+ *
+ * We define the type here to allow use elsewhere in this
+ * interface; actual SecPkcs12AttrsRef manipulation functions
+ * are described later in this header.
+ */
+typedef void *SecPkcs12AttrsRef;
+
+#pragma mark --- Decoder Functions ---
+
+/*
+ * Subsequent to decoding, obtain the components.
+ * These functions can also be used as "getter" functions while encoding.
+ *
+ * Certificates:
+ */
+OSStatus SecPkcs12CertificateCount(
+ SecPkcs12CoderRef coder,
+ CFIndex *numCerts); // RETURNED
+
+OSStatus SecPkcs12CopyCertificate(
+ SecPkcs12CoderRef coder,
+ CFIndex certNum,
+ SecCertificateRef *cert, // RETURNED
+ CFStringRef *friendlyName, // optional, RETURNED
+ CFDataRef *localKeyId, // optional, RETURNED
+ SecPkcs12AttrsRef *attrs); // optional, RETURNED
+
+/*
+ * CRLs. The might change if a SecCrl type is defined elsewhere.
+ * We'll typedef it here to preserve the semantics of this function.
+ */
+typedef CFDataRef SecCrlRef;
+
+OSStatus SecPkcs12CrlCount(
+ SecPkcs12CoderRef coder,
+ CFIndex *numCrls); // RETURNED
+
+OSStatus SecPkcs12CopyCrl(
+ SecPkcs12CoderRef coder,
+ CFIndex crlNum,
+ SecCrlRef *crl, // RETURNED
+ CFStringRef *friendlyName, // optional, RETURNED
+ CFDataRef *localKeyId, // optional, RETURNED
+ SecPkcs12AttrsRef *attrs); // optional, RETURNED
+
+/*
+ * Private keys.
+ */
+OSStatus SecPkcs12PrivateKeyCount(
+ SecPkcs12CoderRef coder,
+ CFIndex *numKeys); // RETURNED
+
+/* currently not implemented : use SecPkcs12GetCssmPrivateKey() */
+OSStatus SecPkcs12CopyPrivateKey(
+ SecPkcs12CoderRef coder,
+ CFIndex keyNum,
+ SecKeyRef *privateKey, // RETURNED
+ CFStringRef *friendlyName, // optional, RETURNED
+ CFDataRef *localKeyId, // optional, RETURNED
+ SecPkcs12AttrsRef *attrs); // optional, RETURNED
+
+/*
+ * The CSSM_KEY_PTR returned by this function has a lifetime
+ * which is the same as the SecPkcs12CoderRef which created it.
+ */
+OSStatus SecPkcs12GetCssmPrivateKey(
+ SecPkcs12CoderRef coder,
+ CFIndex keyNum,
+ CSSM_KEY_PTR *privateKey, // RETURNED
+ CFStringRef *friendlyName, // optional, RETURNED
+ CFDataRef *localKeyId, // optional, RETURNED
+ SecPkcs12AttrsRef *attrs); // optional, RETURNED
+
+/*
+ * Catch-all for other components not currently understood
+ * or supported by this library. An "opaque blob" component
+ * is identified by an OID and is obtained as an opaque data
+ * blob.
+ */
+OSStatus SecPkcs12OpaqueBlobCount(
+ SecPkcs12CoderRef coder,
+ CFIndex *numBlobs); // RETURNED
+
+OSStatus SecPkcs12CopyOpaqueBlob(
+ SecPkcs12CoderRef coder,
+ CFIndex blobNum,
+ CFDataRef *blobOid, // RETURNED
+ CFDataRef *opaqueBlob, // RETURNED
+ CFStringRef *friendlyName, // optional, RETURNED
+ CFDataRef *localKeyId, // optional, RETURNED
+ SecPkcs12AttrsRef *attrs); // optional, RETURNED
+
+#pragma mark --- Encoder Functions ---
+
+/*
+ * Add individual components. "Getter" functions are available
+ * as described above (under "Functions used for decoding").
+ */
+OSStatus SecPkcs12AddCertificate(
+ SecPkcs12CoderRef coder,
+ SecCertificateRef cert,
+ CFStringRef friendlyName, // optional
+ CFDataRef localKeyId, // optional
+ SecPkcs12AttrsRef attrs); // optional
+
+OSStatus SecPkcs12AddCrl(
+ SecPkcs12CoderRef coder,
+ SecCrlRef crl,
+ CFStringRef friendlyName, // optional
+ CFDataRef localKeyId, // optional
+ SecPkcs12AttrsRef attrs); // optional
+
+OSStatus SecPkcs12AddPrivateKey(
+ SecPkcs12CoderRef coder,
+ SecKeyRef privateKey,
+ CFStringRef friendlyName, // optional
+ CFDataRef localKeyId, // optional
+ SecPkcs12AttrsRef attrs); // optional
+
+OSStatus SecPkcs12AddOpaqueBlob(
+ SecPkcs12CoderRef coder,
+ CFDataRef blobOid,
+ CFDataRef opaqueBlob,
+ CFStringRef friendlyName, // optional
+ CFDataRef localKeyId, // optional
+ SecPkcs12AttrsRef attrs); // optional
+
+
+#pragma mark --- Optional Functions ---
+
+/************************************************************
+ *** Optional, rarely used SecPkcs12CoderRef manipulation ***
+ ************************************************************/
+
+/***
+ *** SecPkcs12AttrsRef manipulation. Optional and in fact expected to
+ *** be rarely used, if ever.
+ ***/
+
+/*
+ * A SecPkcs12AttrsRef is an opaque handle referring to an aribtrary
+ * collection of OID/value pairs which can be attached to any
+ * component of a SecPkcs12CoderRef. OIDs and values are expressed
+ * as CFDataRefs. Each OID can have associated with it an arbitrary
+ * number of values.
+ */
+
+/*
+ * Create/destroy.
+ */
+OSStatus SecPkcs12AttrsCreate(
+ SecPkcs12AttrsRef *attrs); // RETURNED
+
+OSStatus SecPkcs12AttrsRelease(
+ SecPkcs12AttrsRef attrs);
+
+/*
+ * Add an OID/value set to an existing SecPkcs12AttrsRef.
+ * Values are a CFArray containing an arbitrary number of
+ * CFDataRefs.
+ */
+OSStatus SecPkcs12AttrsAddAttr(
+ SecPkcs12AttrsRef attrs,
+ CFDataRef attrOid,
+ CFArrayRef attrValues); // an array of CFDataRefs
+
+OSStatus SecPkcs12AttrCount(
+ SecPkcs12AttrsRef attrs,
+ CFIndex *numAttrs); // RETURNED
+
+/*
+ * Obtain n'th oid/value set from an existing SecPkcs12AttrsRef.
+ */
+OSStatus SecPkcs12AttrsGetAttr(
+ SecPkcs12AttrsRef attrs,
+ CFIndex attrNum,
+ CFDataRef *attrOid, // RETURNED
+ CFArrayRef *attrValues); // RETURNED
+
+/***
+ *** Integrity and Privacy Modes
+ ***/
+
+/*
+ * PKCS12 allows for two different modes for each of {privacy,
+ * integrity}. Each of these can be implemented via password
+ * or public key. Per the PKCS12 spec, all four combinations
+ * of these modes are legal. In the current version of this
+ * library, only password privacy and integrity modes are
+ * implemented. These functions are defined here for the
+ * completeness of the API and need never be called by users of
+ * the current implementation.
+ */
+typedef enum {
+ kSecPkcs12ModeUnknown, // uninitialized
+ kSecPkcs12ModePassword,
+ kSecPkcs12ModePublicKey
+} SecPkcs12Mode;
+
+OSStatus SecPkcs12SetIntegrityMode(
+ SecPkcs12CoderRef coder,
+ SecPkcs12Mode mode);
+
+OSStatus SecPkcs12GetIntegrityMode(
+ SecPkcs12CoderRef coder,
+ SecPkcs12Mode *mode); // RETURNED
+
+OSStatus SecPkcs12SetPrivacyMode(
+ SecPkcs12CoderRef coder,
+ SecPkcs12Mode mode);
+
+OSStatus SecPkcs12GetPrivacyMode(
+ SecPkcs12CoderRef coder,
+ SecPkcs12Mode *mode); // RETURNED
+
+/***
+ *** Encryption algorithms
+ ***/
+
+/*
+ * Each individual component of a PKCS12 PFX can be encrypted with
+ * a different encryption algorithm. Typically, Certs and CRLs are
+ * all encrypted with one weak algorithm, and private keys are
+ * encrypted with a stronger algorithm.
+ *
+ * The following functions allow the app to specify, during encoding,
+ * the encryption algorithms to use for the different kinds of
+ * components. These are optional; this library provides appropriate
+ * defaults for these algorithms.
+ */
+OSStatus SecPkcs12SetKeyEncryptionAlg(
+ SecPkcs12CoderRef coder,
+ CFDataRef encryptionAlg);
+
+OSStatus SecPkcs12SetCertCrlEncryptionAlg(
+ SecPkcs12CoderRef coder,
+ CFDataRef encryptionAlg);
+
+/*
+ * Along with an encryption algorithm is an iteration count used for
+ * deriving keys. All of these are optional; reasonable defaults
+ * are provided.
+ *
+ * NOTE: salt is not visible at this API. During encoding,
+ * random values of salt are generated by this module.
+ */
+OSStatus SecPkcs12SetKeyEncryptionIterCount(
+ SecPkcs12CoderRef coder,
+ unsigned iterCount);
+
+OSStatus SecPkcs12SetCertCrlEncryptionIterCount(
+ SecPkcs12CoderRef coder,
+ unsigned iterCount);
+
+OSStatus SecPkcs12SetMacIterCount(
+ SecPkcs12CoderRef coder,
+ unsigned iterCount);
+
+/*
+ * "Getter" versions of the above. During decryption, the values
+ * returned here refer to the *first* such element found (e.g.,
+ * the encryption algorithm for the first key).
+ */
+OSStatus SecPkcs12CopyKeyEncryptionAlg(
+ SecPkcs12CoderRef coder,
+ CFDataRef *encryptionAlg); // RETURNED
+
+OSStatus SecPkcs12CopyCertCrlEncryptionAlg(
+ SecPkcs12CoderRef coder,
+ CFDataRef *encryptionAlg); // RETURNED
+
+OSStatus SecPkcs12CopyKeyEncryptionIterCount(
+ SecPkcs12CoderRef coder,
+ unsigned *iterCount); // RETURNED
+
+OSStatus SecPkcs12CopyCertCrlEncryptionIterCount(
+ SecPkcs12CoderRef coder,
+ unsigned *iterCount); // RETURNED
+
+OSStatus SecPkcs12CopyMacIterCount(
+ SecPkcs12CoderRef coder,
+ unsigned *iterCount); // RETURNED
+
+/*
+ * Avoid importing multiple private keys. Primarily for use by
+ * SecKeychainItemImport(). Behavior depends on the foundOneKey
+ * argument, which indicates whether the current high-level import
+ * has already imported at least one key. If foundOneKey is true,
+ * SecPkcs12Decode() will return errSecMultiplePrivKeys upon
+ * the detection of *any* private keys in the incoming PFX.
+ * If foundOneKey is false, SecPkcs12Decode() will return
+ * errSecMultiplePrivKeys if more than one private key is
+ * found in the incoming PFX.
+ */
+OSStatus SecPkcs12LimitPrivateKeyImport(
+ SecPkcs12CoderRef coder,
+ bool foundOneKey);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SEC_PKCS12_H_ */
+