2  * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 
   4  * The contents of this file constitute Original Code as defined in and are 
   5  * subject to the Apple Public Source License Version 1.2 (the 'License'). 
   6  * You may not use this file except in compliance with the License. Please obtain 
   7  * a copy of the License at http://www.apple.com/publicsource and read it before 
  10  * This Original Code and all software distributed under the License are 
  11  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 
  12  * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 
  13  * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
  14  * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 
  15  * specific language governing rights and limitations under the License. 
  20 // pkcs8.cpp - PKCS8 key wrap/unwrap support. 
  25 #include "AppleCSPUtils.h" 
  26 #include "AppleCSPKeys.h" 
  27 #include <Security/keyTemplates.h> 
  28 #include <security_asn1/SecNssCoder.h> 
  29 #include <security_asn1/nssUtils.h> 
  30 #include "AppleCSPSession.h" 
  31 #include <Security/cssmapple.h> 
  34  * Given a key in PKCS8 format, fill in the following 
  37  *      CSSM_KEYBLOB_FORMAT Format 
  38  *  CSSM_ALGORITHMS AlgorithmId 
  39  *  uint32 LogicalKeySizeInBits 
  41 void AppleCSPSession::pkcs8InferKeyHeader(  
  45          * Incoming key blob is a PrivateKeyInfo. Take it apart 
  46          * to get its algorithm info, from which we infer other 
  49         NSS_PrivateKeyInfo privKeyInfo
; 
  51         CSSM_DATA 
&keyData 
= key
.KeyData
; 
  53         memset(&privKeyInfo
, 0, sizeof(privKeyInfo
)); 
  54         if(coder
.decodeItem(keyData
, kSecAsn1PrivateKeyInfoTemplate
, 
  56                 errorLog0("pkcs8InferKeyHeader decode error\n"); 
  57                 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
); 
  60         CSSM_KEYHEADER 
&hdr 
= key
.KeyHeader
; 
  61         if(!cssmOidToAlg(&privKeyInfo
.algorithm
.algorithm
,  
  63                 errorLog0("pkcs8InferKeyHeader unknown algorithm\n"); 
  64                 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
); 
  67         switch(hdr
.AlgorithmId
) { 
  69                 case CSSM_ALGID_ECDSA
: 
  70                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;  
  74                          * Try openssl style first, though our default when  
  77                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
; 
  81                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_NONE
; 
  86          * Find someone who knows about this key and ask them the 
  87          * key size. infoProvider() throws if no provider found. 
  89         CSSM_KEY_SIZE keySize
; 
  91                 unique_ptr
<CSPKeyInfoProvider
> provider(infoProvider(key
)); 
  92                 provider
->QueryKeySizeInBits(keySize
); 
  94         catch(const CssmError 
&cerror
) { 
  96                  * Special case: DSA private keys keys can be in two forms - FIPS186 
  97                  * (for legacy implementations) and PKCS8 (for openssl). We're wired to 
  98                  * *generate* FIPS186 blobs by default in pkcs8RawKeyFormat(), but to  
  99                  * decode openssl-generated DSA private keys in wrapped FIPS186 format 
 100                  * we have to try both.  
 102                 if((cerror
.error 
== CSSMERR_CSP_INVALID_KEY
) && 
 103                    (hdr
.AlgorithmId 
== CSSM_ALGID_DSA
)) { 
 104                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
; 
 106                                 unique_ptr
<CSPKeyInfoProvider
> provider(infoProvider(key
)); 
 107                                 provider
->QueryKeySizeInBits(keySize
); 
 115                         /* other error, give up */ 
 120                 /* other (non-CSSM) error, give up */ 
 123         hdr
.LogicalKeySizeInBits 
= keySize
.LogicalKeySizeInBits
; 
 127  * When doing a PKCS8 wrap operation on a reference key, this 
 128  * is used to infer the blob type to obtain before the encryption. 
 129  * App can override this with a  
 130  * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT  
 133 CSSM_KEYBLOB_FORMAT 
pkcs8RawKeyFormat( 
 134         CSSM_ALGORITHMS keyAlg
) 
 138                 case CSSM_ALGID_ECDSA
: 
 139                         return CSSM_KEYBLOB_RAW_FORMAT_PKCS8
; 
 141                         return CSSM_KEYBLOB_RAW_FORMAT_FIPS186
; 
 144                         return CSSM_KEYBLOB_RAW_FORMAT_NONE
; 
 149  * When doing a OPENSSL style wrap operation on a reference key, this 
 150  * is used to infer the blob type to obtain before the encryption. 
 151  * App can override this with a  
 152  * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT  
 155 CSSM_KEYBLOB_FORMAT 
opensslRawKeyFormat( 
 156         CSSM_ALGORITHMS keyAlg
) 
 160                         return CSSM_KEYBLOB_RAW_FORMAT_PKCS1
; 
 162                         return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
; 
 163                 case CSSM_ALGID_ECDSA
: 
 164                         return CSSM_KEYBLOB_RAW_FORMAT_PKCS8
; 
 167                         return CSSM_KEYBLOB_RAW_FORMAT_NONE
; 
 172  * Given a key in some kind of openssl format (just subsequent to decryption 
 173  * during an unwrap), fill in the following header fields: 
 175  *      CSSM_KEYBLOB_FORMAT Format 
 176  *  uint32 LogicalKeySizeInBits 
 178 void AppleCSPSession::opensslInferKeyHeader(  
 181         CSSM_KEYHEADER 
&hdr 
= key
.KeyHeader
; 
 182         switch(hdr
.AlgorithmId
) { 
 184                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
; 
 187                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
; 
 189                 case CSSM_ALGID_ECDSA
: 
 190                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
; 
 194                         hdr
.Format 
= CSSM_KEYBLOB_RAW_FORMAT_NONE
; 
 198         /* now figure out the key size by finding a provider for this key */ 
 199         CSSM_KEY_SIZE keySize
; 
 201                 unique_ptr
<CSPKeyInfoProvider
> provider(infoProvider(key
)); 
 202                 provider
->QueryKeySizeInBits(keySize
); 
 205                 /* no recovery possible */ 
 208         hdr
.LogicalKeySizeInBits 
= keySize
.LogicalKeySizeInBits
;