security/nss/lib/ckfw/nssmkey/mrsa.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "ckmk.h"
     7 /* Sigh, For all the talk about 'ease of use', apple has hidden the interfaces
     8  * needed to be able to truly use CSSM. These came from their modification
     9  * to NSS's S/MIME code. The following two functions currently are not
    10  * part of the SecKey.h interface.
    11  */
    12 OSStatus 
    13 SecKeyGetCredentials
    14 (
    15   SecKeyRef keyRef,
    16   CSSM_ACL_AUTHORIZATION_TAG authTag,
    17   int type,
    18   const CSSM_ACCESS_CREDENTIALS **creds
    19 );
    21 /* this function could be implemented using 'SecKeychainItemCopyKeychain' and
    22  * 'SecKeychainGetCSPHandle' */
    23 OSStatus 
    24 SecKeyGetCSPHandle
    25 (
    26   SecKeyRef keyRef,
    27   CSSM_CSP_HANDLE *cspHandle
    28 );
    31 typedef struct ckmkInternalCryptoOperationRSAPrivStr 
    32                ckmkInternalCryptoOperationRSAPriv;
    33 struct ckmkInternalCryptoOperationRSAPrivStr
    34 {
    35   NSSCKMDCryptoOperation mdOperation;
    36   NSSCKMDMechanism     *mdMechanism;
    37   ckmkInternalObject *iKey;
    38   NSSItem  *buffer;
    39   CSSM_CC_HANDLE cssmContext;
    40 };
    42 typedef enum {
    43   CKMK_DECRYPT,
    44   CKMK_SIGN
    45 } ckmkRSAOpType;
    47 /*
    48  * ckmk_mdCryptoOperationRSAPriv_Create
    49  */
    50 static NSSCKMDCryptoOperation *
    51 ckmk_mdCryptoOperationRSAPriv_Create
    52 (
    53   const NSSCKMDCryptoOperation *proto,
    54   NSSCKMDMechanism *mdMechanism,
    55   NSSCKMDObject *mdKey,
    56   ckmkRSAOpType type,
    57   CK_RV *pError
    58 )
    59 {
    60   ckmkInternalObject *iKey = (ckmkInternalObject *)mdKey->etc;
    61   const NSSItem *classItem = nss_ckmk_FetchAttribute(iKey, CKA_CLASS, pError);
    62   const NSSItem *keyType = nss_ckmk_FetchAttribute(iKey, CKA_KEY_TYPE, pError);
    63   ckmkInternalCryptoOperationRSAPriv *iOperation;
    64   SecKeyRef privateKey;
    65   OSStatus macErr;
    66   CSSM_RETURN cssmErr;
    67   const CSSM_KEY *cssmKey;
    68   CSSM_CSP_HANDLE cspHandle;
    69   const CSSM_ACCESS_CREDENTIALS *creds = NULL;
    70   CSSM_CC_HANDLE cssmContext;
    71   CSSM_ACL_AUTHORIZATION_TAG authType;
    73   /* make sure we have the right objects */
    74   if (((const NSSItem *)NULL == classItem) ||
    75       (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
    76       (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) ||
    77       ((const NSSItem *)NULL == keyType) ||
    78       (sizeof(CK_KEY_TYPE) != keyType->size) ||
    79       (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) {
    80     *pError =  CKR_KEY_TYPE_INCONSISTENT;
    81     return (NSSCKMDCryptoOperation *)NULL;
    82   }
    84   privateKey = (SecKeyRef) iKey->u.item.itemRef;
    85   macErr = SecKeyGetCSSMKey(privateKey, &cssmKey);
    86   if (noErr != macErr) {
    87     CKMK_MACERR("Getting CSSM Key", macErr);
    88     *pError = CKR_KEY_HANDLE_INVALID;
    89     return (NSSCKMDCryptoOperation *)NULL;
    90   }
    91   macErr = SecKeyGetCSPHandle(privateKey, &cspHandle);
    92   if (noErr != macErr) {
    93     CKMK_MACERR("Getting CSP for Key", macErr);
    94     *pError = CKR_KEY_HANDLE_INVALID;
    95     return (NSSCKMDCryptoOperation *)NULL;
    96   }
    97   switch (type) {
    98   case CKMK_DECRYPT:
    99     authType = CSSM_ACL_AUTHORIZATION_DECRYPT;
   100     break;
   101   case CKMK_SIGN:
   102     authType = CSSM_ACL_AUTHORIZATION_SIGN;
   103     break;
   104   default:
   105     *pError = CKR_GENERAL_ERROR;
   106 #ifdef DEBUG
   107     fprintf(stderr,"RSAPriv_Create: bad type = %d\n", type);
   108 #endif
   109     return (NSSCKMDCryptoOperation *)NULL;
   110   }
   112   macErr = SecKeyGetCredentials(privateKey, authType, 0, &creds);
   113   if (noErr != macErr) {
   114     CKMK_MACERR("Getting Credentials for Key", macErr);
   115     *pError = CKR_KEY_HANDLE_INVALID;
   116     return (NSSCKMDCryptoOperation *)NULL;
   117   }
   119   switch (type) {
   120   case CKMK_DECRYPT:
   121     cssmErr = CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA,
   122                         creds, cssmKey, CSSM_PADDING_PKCS1, &cssmContext);
   123     break;
   124   case CKMK_SIGN:
   125     cssmErr = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA,
   126                                               creds, cssmKey, &cssmContext);
   127     break;
   128   default:
   129     *pError = CKR_GENERAL_ERROR;
   130 #ifdef DEBUG
   131     fprintf(stderr,"RSAPriv_Create: bad type = %d\n", type);
   132 #endif
   133     return (NSSCKMDCryptoOperation *)NULL;
   134   }
   135   if (noErr != cssmErr) {
   136     CKMK_MACERR("Getting Context for Key", cssmErr);
   137     *pError = CKR_GENERAL_ERROR;
   138     return (NSSCKMDCryptoOperation *)NULL;
   139   }
   141   iOperation = nss_ZNEW(NULL, ckmkInternalCryptoOperationRSAPriv);
   142   if ((ckmkInternalCryptoOperationRSAPriv *)NULL == iOperation) {
   143     *pError = CKR_HOST_MEMORY;
   144     return (NSSCKMDCryptoOperation *)NULL;
   145   }
   146   iOperation->mdMechanism = mdMechanism;
   147   iOperation->iKey = iKey;
   148   iOperation->cssmContext = cssmContext;
   150   nsslibc_memcpy(&iOperation->mdOperation, 
   151                  proto, sizeof(NSSCKMDCryptoOperation));
   152   iOperation->mdOperation.etc = iOperation;
   154   return &iOperation->mdOperation;
   155 }
   157 static void
   158 ckmk_mdCryptoOperationRSAPriv_Destroy
   159 (
   160   NSSCKMDCryptoOperation *mdOperation,
   161   NSSCKFWCryptoOperation *fwOperation,
   162   NSSCKMDInstance *mdInstance,
   163   NSSCKFWInstance *fwInstance
   164 )
   165 {
   166   ckmkInternalCryptoOperationRSAPriv *iOperation =
   167        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
   169   if (iOperation->buffer) {
   170     nssItem_Destroy(iOperation->buffer);
   171   }
   172   if (iOperation->cssmContext) {
   173     CSSM_DeleteContext(iOperation->cssmContext);
   174   }
   175   nss_ZFreeIf(iOperation);
   176   return;
   177 }
   179 static CK_ULONG
   180 ckmk_mdCryptoOperationRSA_GetFinalLength
   181 (
   182   NSSCKMDCryptoOperation *mdOperation,
   183   NSSCKFWCryptoOperation *fwOperation,
   184   NSSCKMDSession *mdSession,
   185   NSSCKFWSession *fwSession,
   186   NSSCKMDToken *mdToken,
   187   NSSCKFWToken *fwToken,
   188   NSSCKMDInstance *mdInstance,
   189   NSSCKFWInstance *fwInstance,
   190   CK_RV *pError
   191 )
   192 {
   193   ckmkInternalCryptoOperationRSAPriv *iOperation =
   194        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
   195   const NSSItem *modulus = 
   196        nss_ckmk_FetchAttribute(iOperation->iKey, CKA_MODULUS, pError);
   198   return modulus->size;
   199 }
   202 /*
   203  * ckmk_mdCryptoOperationRSADecrypt_GetOperationLength
   204  * we won't know the length until we actually decrypt the
   205  * input block. Since we go to all the work to decrypt the
   206  * the block, we'll save if for when the block is asked for
   207  */
   208 static CK_ULONG
   209 ckmk_mdCryptoOperationRSADecrypt_GetOperationLength
   210 (
   211   NSSCKMDCryptoOperation *mdOperation,
   212   NSSCKFWCryptoOperation *fwOperation,
   213   NSSCKMDSession *mdSession,
   214   NSSCKFWSession *fwSession,
   215   NSSCKMDToken *mdToken,
   216   NSSCKFWToken *fwToken,
   217   NSSCKMDInstance *mdInstance,
   218   NSSCKFWInstance *fwInstance,
   219   const NSSItem *input,
   220   CK_RV *pError
   221 )
   222 {
   223   ckmkInternalCryptoOperationRSAPriv *iOperation =
   224        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc; 
   225   CSSM_DATA cssmInput;
   226   CSSM_DATA cssmOutput = { 0, NULL };
   227   PRUint32  bytesDecrypted;
   228   CSSM_DATA remainder = { 0, NULL };
   229   NSSItem output;
   230   CSSM_RETURN cssmErr;
   232   if (iOperation->buffer) {
   233     return iOperation->buffer->size;
   234   }
   236   cssmInput.Data = input->data;
   237   cssmInput.Length = input->size;
   239   cssmErr = CSSM_DecryptData(iOperation->cssmContext, 
   240 			     &cssmInput, 1, &cssmOutput, 1,
   241 			     &bytesDecrypted, &remainder);
   242   if (CSSM_OK != cssmErr) {
   243     CKMK_MACERR("Decrypt Failed", cssmErr);
   244     *pError = CKR_DATA_INVALID;
   245     return 0;
   246   }
   247   /* we didn't suppy any buffers, so it should all be in remainder */
   248   output.data = nss_ZNEWARRAY(NULL, char, bytesDecrypted + remainder.Length);
   249   if (NULL == output.data) {
   250     free(cssmOutput.Data);
   251     free(remainder.Data);
   252     *pError = CKR_HOST_MEMORY;
   253     return 0;
   254   }
   255   output.size = bytesDecrypted + remainder.Length;
   257   if (0 != bytesDecrypted) {
   258     nsslibc_memcpy(output.data, cssmOutput.Data, bytesDecrypted);
   259     free(cssmOutput.Data);
   260   }
   261   if (0 != remainder.Length) {
   262     nsslibc_memcpy(((char *)output.data)+bytesDecrypted, 
   263 	           remainder.Data, remainder.Length);
   264     free(remainder.Data);
   265   }
   267   iOperation->buffer = nssItem_Duplicate(&output, NULL, NULL);
   268   nss_ZFreeIf(output.data);
   269   if ((NSSItem *) NULL == iOperation->buffer) {
   270     *pError = CKR_HOST_MEMORY;
   271     return 0;
   272   }
   274   return iOperation->buffer->size;
   275 }
   277 /*
   278  * ckmk_mdCryptoOperationRSADecrypt_UpdateFinal
   279  *
   280  * NOTE: ckmk_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to 
   281  * have been called previously.
   282  */
   283 static CK_RV
   284 ckmk_mdCryptoOperationRSADecrypt_UpdateFinal
   285 (
   286   NSSCKMDCryptoOperation *mdOperation,
   287   NSSCKFWCryptoOperation *fwOperation,
   288   NSSCKMDSession *mdSession,
   289   NSSCKFWSession *fwSession,
   290   NSSCKMDToken *mdToken,
   291   NSSCKFWToken *fwToken,
   292   NSSCKMDInstance *mdInstance,
   293   NSSCKFWInstance *fwInstance,
   294   const NSSItem *input,
   295   NSSItem *output
   296 )
   297 {
   298   ckmkInternalCryptoOperationRSAPriv *iOperation =
   299        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc; 
   300   NSSItem *buffer = iOperation->buffer;
   302   if ((NSSItem *)NULL == buffer) {
   303     return CKR_GENERAL_ERROR;
   304   }
   305   nsslibc_memcpy(output->data, buffer->data, buffer->size);
   306   output->size = buffer->size;
   307   return CKR_OK;
   308 }
   310 /*
   311  * ckmk_mdCryptoOperationRSASign_UpdateFinal
   312  *
   313  */
   314 static CK_RV
   315 ckmk_mdCryptoOperationRSASign_UpdateFinal
   316 (
   317   NSSCKMDCryptoOperation *mdOperation,
   318   NSSCKFWCryptoOperation *fwOperation,
   319   NSSCKMDSession *mdSession,
   320   NSSCKFWSession *fwSession,
   321   NSSCKMDToken *mdToken,
   322   NSSCKFWToken *fwToken,
   323   NSSCKMDInstance *mdInstance,
   324   NSSCKFWInstance *fwInstance,
   325   const NSSItem *input,
   326   NSSItem *output
   327 )
   328 {
   329   ckmkInternalCryptoOperationRSAPriv *iOperation =
   330        (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
   331   CSSM_DATA cssmInput;
   332   CSSM_DATA cssmOutput = { 0, NULL };
   333   CSSM_RETURN cssmErr;
   335   cssmInput.Data = input->data;
   336   cssmInput.Length = input->size; 
   338   cssmErr = CSSM_SignData(iOperation->cssmContext, &cssmInput, 1,
   339                           CSSM_ALGID_NONE, &cssmOutput);
   340   if (CSSM_OK != cssmErr) {
   341     CKMK_MACERR("Signed Failed", cssmErr);
   342     return CKR_FUNCTION_FAILED;
   343   }
   344   if (cssmOutput.Length > output->size) {
   345     free(cssmOutput.Data);
   346     return CKR_BUFFER_TOO_SMALL;
   347   }
   348   nsslibc_memcpy(output->data, cssmOutput.Data, cssmOutput.Length);
   349   free(cssmOutput.Data);
   350   output->size = cssmOutput.Length;
   352   return CKR_OK;
   353 }
   356 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
   357 ckmk_mdCryptoOperationRSADecrypt_proto = {
   358   NULL, /* etc */
   359   ckmk_mdCryptoOperationRSAPriv_Destroy,
   360   NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */
   361   ckmk_mdCryptoOperationRSADecrypt_GetOperationLength,
   362   NULL, /* Final - not needed for one shot operation */
   363   NULL, /* Update - not needed for one shot operation */
   364   NULL, /* DigetUpdate - not needed for one shot operation */
   365   ckmk_mdCryptoOperationRSADecrypt_UpdateFinal,
   366   NULL, /* UpdateCombo - not needed for one shot operation */
   367   NULL, /* DigetKey - not needed for one shot operation */
   368   (void *)NULL /* null terminator */
   369 };
   371 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
   372 ckmk_mdCryptoOperationRSASign_proto = {
   373   NULL, /* etc */
   374   ckmk_mdCryptoOperationRSAPriv_Destroy,
   375   ckmk_mdCryptoOperationRSA_GetFinalLength,
   376   NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */
   377   NULL, /* Final - not needed for one shot operation */
   378   NULL, /* Update - not needed for one shot operation */
   379   NULL, /* DigetUpdate - not needed for one shot operation */
   380   ckmk_mdCryptoOperationRSASign_UpdateFinal,
   381   NULL, /* UpdateCombo - not needed for one shot operation */
   382   NULL, /* DigetKey - not needed for one shot operation */
   383   (void *)NULL /* null terminator */
   384 };
   386 /********** NSSCKMDMechansim functions ***********************/
   387 /*
   388  * ckmk_mdMechanismRSA_Destroy
   389  */
   390 static void
   391 ckmk_mdMechanismRSA_Destroy
   392 (
   393   NSSCKMDMechanism *mdMechanism,
   394   NSSCKFWMechanism *fwMechanism,
   395   NSSCKMDInstance *mdInstance,
   396   NSSCKFWInstance *fwInstance
   397 )
   398 {
   399   nss_ZFreeIf(fwMechanism);
   400 }
   402 /*
   403  * ckmk_mdMechanismRSA_GetMinKeySize
   404  */
   405 static CK_ULONG
   406 ckmk_mdMechanismRSA_GetMinKeySize
   407 (
   408   NSSCKMDMechanism *mdMechanism,
   409   NSSCKFWMechanism *fwMechanism,
   410   NSSCKMDToken *mdToken,
   411   NSSCKFWToken *fwToken,
   412   NSSCKMDInstance *mdInstance,
   413   NSSCKFWInstance *fwInstance,
   414   CK_RV *pError
   415 )
   416 {
   417   return 384;
   418 }
   420 /*
   421  * ckmk_mdMechanismRSA_GetMaxKeySize
   422  */
   423 static CK_ULONG
   424 ckmk_mdMechanismRSA_GetMaxKeySize
   425 (
   426   NSSCKMDMechanism *mdMechanism,
   427   NSSCKFWMechanism *fwMechanism,
   428   NSSCKMDToken *mdToken,
   429   NSSCKFWToken *fwToken,
   430   NSSCKMDInstance *mdInstance,
   431   NSSCKFWInstance *fwInstance,
   432   CK_RV *pError
   433 )
   434 {
   435   return 16384;
   436 }
   438 /*
   439  * ckmk_mdMechanismRSA_DecryptInit
   440  */
   441 static NSSCKMDCryptoOperation * 
   442 ckmk_mdMechanismRSA_DecryptInit
   443 (
   444   NSSCKMDMechanism *mdMechanism,
   445   NSSCKFWMechanism *fwMechanism,
   446   CK_MECHANISM     *pMechanism,
   447   NSSCKMDSession *mdSession,
   448   NSSCKFWSession *fwSession,
   449   NSSCKMDToken *mdToken,
   450   NSSCKFWToken *fwToken,
   451   NSSCKMDInstance *mdInstance,
   452   NSSCKFWInstance *fwInstance,
   453   NSSCKMDObject *mdKey,
   454   NSSCKFWObject *fwKey,
   455   CK_RV *pError
   456 )
   457 {
   458   return ckmk_mdCryptoOperationRSAPriv_Create(
   459 		&ckmk_mdCryptoOperationRSADecrypt_proto,
   460 		mdMechanism, mdKey, CKMK_DECRYPT, pError);
   461 }
   463 /*
   464  * ckmk_mdMechanismRSA_SignInit
   465  */
   466 static NSSCKMDCryptoOperation * 
   467 ckmk_mdMechanismRSA_SignInit
   468 (
   469   NSSCKMDMechanism *mdMechanism,
   470   NSSCKFWMechanism *fwMechanism,
   471   CK_MECHANISM     *pMechanism,
   472   NSSCKMDSession *mdSession,
   473   NSSCKFWSession *fwSession,
   474   NSSCKMDToken *mdToken,
   475   NSSCKFWToken *fwToken,
   476   NSSCKMDInstance *mdInstance,
   477   NSSCKFWInstance *fwInstance,
   478   NSSCKMDObject *mdKey,
   479   NSSCKFWObject *fwKey,
   480   CK_RV *pError
   481 )
   482 {
   483   return ckmk_mdCryptoOperationRSAPriv_Create(
   484 		&ckmk_mdCryptoOperationRSASign_proto,
   485 		mdMechanism, mdKey, CKMK_SIGN, pError);
   486 }
   489 NSS_IMPLEMENT_DATA const NSSCKMDMechanism
   490 nss_ckmk_mdMechanismRSA = {
   491   (void *)NULL, /* etc */
   492   ckmk_mdMechanismRSA_Destroy,
   493   ckmk_mdMechanismRSA_GetMinKeySize,
   494   ckmk_mdMechanismRSA_GetMaxKeySize,
   495   NULL, /* GetInHardware - default false */
   496   NULL, /* EncryptInit - default errs */
   497   ckmk_mdMechanismRSA_DecryptInit,
   498   NULL, /* DigestInit - default errs*/
   499   ckmk_mdMechanismRSA_SignInit,
   500   NULL, /* VerifyInit - default errs */
   501   ckmk_mdMechanismRSA_SignInit,  /* SignRecoverInit */
   502   NULL, /* VerifyRecoverInit - default errs */
   503   NULL, /* GenerateKey - default errs */
   504   NULL, /* GenerateKeyPair - default errs */
   505   NULL, /* GetWrapKeyLength - default errs */
   506   NULL, /* WrapKey - default errs */
   507   NULL, /* UnwrapKey - default errs */
   508   NULL, /* DeriveKey - default errs */
   509   (void *)NULL /* null terminator */
   510 };

mercurial