/*
 * find the best key wrap mechanism for this slot.
 */
CK_MECHANISM_TYPE
PK11_GetBestWrapMechanism(PK11SlotInfo *slot)
{
    int i;
    for (i=0; i < wrapMechanismCount; i++) {
	if (PK11_DoesMechanism(slot,wrapMechanismList[i])) {
	    return wrapMechanismList[i];
	}
    }
    return CKM_INVALID_MECHANISM;
}
Exemple #2
0
static CK_MECHANISM_TYPE
crmf_get_best_privkey_wrap_mechanism(PK11SlotInfo *slot) 
{
    CK_MECHANISM_TYPE privKeyPadMechs[] = { CKM_DES3_CBC_PAD,
					    CKM_CAST5_CBC_PAD,
					    CKM_DES_CBC_PAD,
					    CKM_IDEA_CBC_PAD,
					    CKM_CAST3_CBC_PAD,
					    CKM_CAST_CBC_PAD,
					    CKM_RC5_CBC_PAD,
					    CKM_RC2_CBC_PAD,
					    CKM_CDMF_CBC_PAD };
    int mechCount = sizeof(privKeyPadMechs)/sizeof(privKeyPadMechs[0]);
    int i;

    for (i=0; i < mechCount; i++) {
        if (PK11_DoesMechanism(slot, privKeyPadMechs[i])) {
	    return privKeyPadMechs[i];
	}
    }
    return CKM_INVALID_MECHANISM;
}
Exemple #3
0
/* RSA sign/decrypt with the key, signature happens 'in place' */
vcard_7816_status_t
vcard_emul_rsa_op(VCard *card, VCardKey *key,
                  unsigned char *buffer, int buffer_size)
{
    SECKEYPrivateKey *priv_key;
    unsigned signature_len;
    PK11SlotInfo *slot;
    SECStatus rv;
    unsigned char buf[2048];
    unsigned char *bp = NULL;
    int pad_len;
    vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;

    if ((!nss_emul_init) || (key == NULL)) {
        /* couldn't get the key, indicate that we aren't logged in */
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
    }
    priv_key = vcard_emul_get_nss_key(key);
    if (priv_key == NULL) {
        /* couldn't get the key, indicate that we aren't logged in */
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
    }
    slot = vcard_emul_card_get_slot(card);

    /*
     * this is only true of the rsa signature
     */
    signature_len = PK11_SignatureLen(priv_key);
    if (buffer_size != signature_len) {
        return  VCARD7816_STATUS_ERROR_DATA_INVALID;
    }
    /* be able to handle larger keys if necessariy */
    bp = &buf[0];
    if (sizeof(buf) < signature_len) {
        bp = g_malloc(signature_len);
    }

    /*
     * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
     * choke when they try to do the actual operations. Try to detect
     * those cases and treat them as if the token didn't claim support for
     * X_509.
     */
    if (key->failedX509 != VCardEmulTrue
                              && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
        rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
                                 buffer, buffer_size);
        if (rv == SECSuccess) {
            assert(buffer_size == signature_len);
            memcpy(buffer, bp, signature_len);
            key->failedX509 = VCardEmulFalse;
            goto cleanup;
        }
        /*
         * we've had a successful X509 operation, this failure must be
         * somethine else
         */
        if (key->failedX509 == VCardEmulFalse) {
            ret = vcard_emul_map_error(PORT_GetError());
            goto cleanup;
        }
        /*
         * key->failedX509 must be Unknown at this point, try the
         * non-x_509 case
         */
    }
    /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
    /* is this a PKCS #1 formatted signature? */
    if ((buffer[0] == 0) && (buffer[1] == 1)) {
        int i;

        for (i = 2; i < buffer_size; i++) {
            /* rsa signature pad */
            if (buffer[i] != 0xff) {
                break;
            }
        }
        if ((i < buffer_size) && (buffer[i] == 0)) {
            /* yes, we have a properly formated PKCS #1 signature */
            /*
             * NOTE: even if we accidentally got an encrypt buffer, which
             * through shear luck started with 00, 01, ff, 00, it won't matter
             * because the resulting Sign operation will effectively decrypt
             * the real buffer.
             */
            SECItem signature;
            SECItem hash;

            i++;
            hash.data = &buffer[i];
            hash.len = buffer_size - i;
            signature.data = bp;
            signature.len = signature_len;
            rv = PK11_Sign(priv_key,  &signature, &hash);
            if (rv != SECSuccess) {
                ret = vcard_emul_map_error(PORT_GetError());
                goto cleanup;
            }
            assert(buffer_size == signature.len);
            memcpy(buffer, bp, signature.len);
            /*
             * we got here because either the X509 attempt failed, or the
             * token couldn't do the X509 operation, in either case stay
             * with the PKCS version for future operations on this key
             */
            key->failedX509 = VCardEmulTrue;
            goto cleanup;
        }
    }
    pad_len = buffer_size - signature_len;
    assert(pad_len < 4);
    /*
     * OK now we've decrypted the payload, package it up in PKCS #1 for the
     * upper layer.
     */
    buffer[0] = 0;
    buffer[1] = 2; /* RSA_encrypt  */
    pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
    /*
     * padding for PKCS #1 encrypted data is a string of random bytes. The
     * random butes protect against potential decryption attacks against RSA.
     * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
     * them. This shouldn't matter to the upper level code which should just
     * strip this code out anyway, so We'll pad with a constant 3.
     */
    memset(&buffer[2], 0x03, pad_len);
    pad_len += 2; /* index to the end of the pad */
    buffer[pad_len] = 0;
    pad_len++; /* index to the start of the data */
    memcpy(&buffer[pad_len], bp, signature_len);
    /*
     * we got here because either the X509 attempt failed, or the
     * token couldn't do the X509 operation, in either case stay
     * with the PKCS version for future operations on this key
     */
    key->failedX509 = VCardEmulTrue;
cleanup:
    if (bp != buf) {
        g_free(bp);
    }
    return ret;
}
Exemple #4
0
/*
 * CreatePk11PinStore
 */
int
CreatePk11PinStore(Pk11PinStore **out, const char *tokenName, const char *pin)
{
    int err = PIN_SUCCESS;
    Pk11PinStore *store;

    do {

        store = (Pk11PinStore*)malloc(sizeof(Pk11PinStore));
        if (store == 0) { err = PIN_NOMEMORY; break; }

        /* Low-level init */
        store->key = 0;
        store->params = 0;
        store->crypt = 0;

        /* Use the tokenName to find a PKCS11 slot */
        store->slot = PK11_FindSlotByName((char *)tokenName);
        if (store->slot == 0) { err = PIN_NOSUCHTOKEN; break; }

        /* Check the password/PIN.  This allows access to the token */
        {
            SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin);

            if (rv == SECSuccess)
                ;
            else if (rv == SECWouldBlock)
            {
                /* NSS returns a blocking error when the pin is wrong */
                err = PIN_INCORRECTPW;
                break;
            }
            else
            {
                err = PIN_SYSTEMERROR;
                break;
            }
        }

        /* Find the mechanism that this token can do */
        {
            const mech_item *tp;

            store->mech = 0;
            for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++)
            {
                if (PK11_DoesMechanism(store->slot, tp->type))
                {
                    store->mech = (mech_item *)tp;
                    break;
                }
            }
            /* Default to a mechanism (probably on the internal token */
            if (store->mech == 0) {
                store->mech = &dflt_mech;
            }
        }

        /* Generate a key and parameters to do the encryption */
#if NSS_VMAJOR >= 3 && (NSS_VMINOR <= 9 || (NSS_VMINOR <= 10 && NSS_VPATCH == 0))
        store->key = PK11_KeyGen(store->slot, store->mech->type,
                       0, 0, 0);
#else
        store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type,
                     NULL, 0, NULL, CKF_ENCRYPT|CKF_DECRYPT, PR_FALSE, NULL);
#endif
        if (store->key == 0)
        {
            /* PR_SetError(xxx); */
            err = PIN_SYSTEMERROR;
            break;
        }

        store->params = PK11_GenerateNewParam(store->mech->type, store->key);
        if (store->params == 0)
        {
            err = PIN_SYSTEMERROR;
            break;
        }

        /* Compute the size of the encrypted data including necessary padding */
        {
            int blocksize = PK11_GetBlockSize(store->mech->type, 0);

            store->length = strlen(pin)+1;

            /* Compute padded size - 0 means stream cipher */
            if (blocksize != 0)
            {
                store->length += blocksize - (store->length % blocksize);
            }

            store->crypt = (unsigned char *)malloc(store->length);
            if (!store->crypt) { err = PIN_NOMEMORY; break; }
        }

        /* Encrypt */
        {
            unsigned char *plain;
            PK11Context *ctx;
            SECStatus rv;
            int outLen;

            plain = (unsigned char *)malloc(store->length);
            if (!plain) { err = PIN_NOMEMORY; break; }

            /* Pad with 0 bytes */
            memset(plain, 0, store->length);
            strcpy((char *)plain, pin);

            ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT,
                    store->key, store->params);
            if (!ctx) { err = PIN_SYSTEMERROR; break; }

            do {
                rv = PK11_CipherOp(ctx, store->crypt, &outLen, store->length,
                       plain, store->length);
                if (rv) break;

                rv = PK11_Finalize(ctx);
            } while(0);

            PK11_DestroyContext(ctx, PR_TRUE);
            memset(plain, 0, store->length);
            free(plain);

            if (rv) err = PIN_SYSTEMERROR;
        }
    } while(0);

    if (err)
    {
        DestroyPk11PinStore(store);
        store = 0;
    }

    *out = store;
    return err;
}
/*
 * SVRCORE_CreatePk11PinStore
 */
SVRCOREError
SVRCORE_CreatePk11PinStore(
  SVRCOREPk11PinStore **out,
  const char *tokenName, const char *pin)
{
  SVRCOREError err;
  SVRCOREPk11PinStore *store;

  do {
    err = SVRCORE_Success;

    store = (SVRCOREPk11PinStore*)malloc(sizeof *store);
    if (store == 0) { err = SVRCORE_NoMemory_Error; break; }

    /* Low-level init */
    store->slot = 0;
    store->key = 0;
    store->params = 0;
    store->crypt = 0;

    /* Use the tokenName to find a PKCS11 slot */
    store->slot = PK11_FindSlotByName((char *)tokenName);
    if (store->slot == 0) { err = SVRCORE_NoSuchToken_Error; break; }

    /* Check the password/PIN.  This allows access to the token */
    {
      SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin);

      if (rv == SECSuccess)
        ;
      else if (rv == SECWouldBlock)
      {
        err = SVRCORE_IncorrectPassword_Error;
        break;
      }
      else
      {
        err = SVRCORE_System_Error;
        break;
      }
    }

    /* Find the mechanism that this token can do */
    {
      const mech_item *tp;

      store->mech = 0;
      for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++)
      {
        if (PK11_DoesMechanism(store->slot, tp->type))
        {
          store->mech = tp;
          break;
        }
      }
      /* Default to a mechanism (probably on the internal token */
      if (store->mech == 0)
        store->mech = &dflt_mech;
    }

    /* Generate a key and parameters to do the encryption */
    store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type,
                 0, 0, 0, CKF_ENCRYPT|CKF_DECRYPT,
                 0, 0);
    if (store->key == 0)
    {
      /* PR_SetError(xxx); */
      err = SVRCORE_System_Error;
      break;
    }

    store->params = PK11_GenerateNewParam(store->mech->type, store->key);
    if (store->params == 0)
    {
      err = SVRCORE_System_Error;
      break;
    }

    /* Compute the size of the encrypted data including necessary padding */
    {
      int blocksize = PK11_GetBlockSize(store->mech->type, 0);

      store->length = strlen(pin)+1;

      /* Compute padded size - 0 means stream cipher */
      if (blocksize != 0)
      {
        store->length += blocksize - (store->length % blocksize);
      }

      store->crypt = (unsigned char *)malloc(store->length);
      if (!store->crypt) { err = SVRCORE_NoMemory_Error; break; }
    }

    /* Encrypt */
    {
      unsigned char *plain;
      PK11Context *ctx;
      SECStatus rv;
      int outLen;

      plain = (unsigned char *)malloc(store->length);
      if (!plain) { err = SVRCORE_NoMemory_Error; break; }

      /* Pad with 0 bytes */
      memset(plain, 0, store->length);
      strcpy((char *)plain, pin);

      ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT,
              store->key, store->params);
      if (!ctx) { err = SVRCORE_System_Error; break; }

      do {
        rv = PK11_CipherOp(ctx, store->crypt, &outLen, store->length,
               plain, store->length);
        if (rv) break;

        rv = PK11_Finalize(ctx);
      } while(0);

      PK11_DestroyContext(ctx, PR_TRUE);
      memset(plain, 0, store->length);
      free(plain);

      if (rv) err = SVRCORE_System_Error;
    }
  } while(0);

  if (err)
  {
    SVRCORE_DestroyPk11PinStore(store);
    store = 0;
  }

  *out = store;
  return err;
}