/* * Copyright (c) 2003-2004 Apple Computer, 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_ */