/* Following used for RSA */ int PKCS11_sign(int type, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, PKCS11_KEY * key) { int rv, ssl = ((type == NID_md5_sha1) ? 1 : 0); unsigned char *encoded = NULL; int sigsize; if (key == NULL) return 0; CHECK_KEY_FORK(key); sigsize = PKCS11_get_key_size(key); if (ssl) { if ((m_len != 36) /* SHA1 + MD5 */ || ((m_len + RSA_PKCS1_PADDING_SIZE) > (unsigned)sigsize)) { return 0; /* the size is wrong */ } } else { ASN1_TYPE parameter = { V_ASN1_NULL, { NULL } }; ASN1_STRING digest = { m_len, V_ASN1_OCTET_STRING, (unsigned char *)m, 0 }; X509_ALGOR algor = { NULL, ¶meter }; X509_SIG digest_info = { &algor, &digest }; int size; /* Fetch the OID of the algorithm used */ if ((algor.algorithm = OBJ_nid2obj(type)) && (algor.algorithm) && /* Get the size of the encoded DigestInfo */ (size = i2d_X509_SIG(&digest_info, NULL)) && /* Check that size is compatible with PKCS#11 padding */ (size + RSA_PKCS1_PADDING_SIZE <= sigsize) && (encoded = OPENSSL_malloc(sigsize))) { unsigned char *tmp = encoded; /* Actually do the encoding */ i2d_X509_SIG(&digest_info,&tmp); m = encoded; m_len = size; } else { return 0; } } rv = PKCS11_private_encrypt(m_len, m, sigret, key, RSA_PKCS1_PADDING); if (rv <= 0) rv = 0; else { *siglen = rv; rv = 1; } if (encoded != NULL) /* NULL on SSL case */ OPENSSL_free(encoded); return rv; }
ByteArray SmartcardSlot::decrypt(std::string &keyId, std::string &pin, ByteArray &data) throw (SmartcardModuleException) { int rc, found = 0, nret, keySize, j, errorCode; PKCS11_KEY *keys; ByteArray ret; unsigned int nKeys, i; std::string idTmp; char *bufferId; ERR_clear_error(); if (pin.size() < 4 || pin.size() > 8) { throw SmartcardModuleException(SmartcardModuleException::INVALID_PIN, "SmartcardSlot::decrypt", true); } rc = PKCS11_login(this->slot, 0, pin.c_str()); if (rc != 0) { errorCode = ERR_GET_REASON(ERR_get_error()); if (errorCode == SmartcardModuleException::BLOCKED_PIN) { throw SmartcardModuleException(SmartcardModuleException::BLOCKED_PIN, "SmartcardSlot::decrypt", true); } else if (errorCode == SmartcardModuleException::INVALID_PIN) { throw SmartcardModuleException(SmartcardModuleException::INVALID_PIN, "SmartcardSlot::decrypt", true); } else { throw SmartcardModuleException(SmartcardModuleException::UNKNOWN, "SmartcardSlot::decrypt", true); } } rc = PKCS11_enumerate_keys(this->slot[0].token, &keys, &nKeys); if (rc != 0 || nKeys == 0) { PKCS11_logout(this->slot); throw SmartcardModuleException(SmartcardModuleException::ENUMERATING_PRIVATE_KEYS, "SmartcardSlot::decrypt", true); } found = -1; for (i=0;(i<nKeys)&&(found==-1);i++) { bufferId = (char *)calloc((keys[i].id_len * 2) + 1, sizeof(char)); for (j=0;j<keys[i].id_len;j++) { sprintf(&(bufferId[j*2]), "%02X", keys[i].id[j]); } idTmp = bufferId; free(bufferId); if (keyId == idTmp) { found = i; keySize = PKCS11_get_key_size(&keys[i]); } } if (found < 0) { PKCS11_logout(this->slot); //TODO: apagar todas as chaves encontradas, não tem na libp11 throw SmartcardModuleException(SmartcardModuleException::ID_NOT_FOUND, "SmartcardSlot::decrypt", true); } ret = ByteArray(keySize); nret = PKCS11_private_decrypt(data.size(), data.getDataPointer(), ret.getDataPointer(), &keys[found], RSA_PKCS1_PADDING); PKCS11_logout(this->slot); if (nret <= 0) { throw SmartcardModuleException(SmartcardModuleException::DECRYPTING_DATA, "SmartcardSlot::decrypt", true); } ret = ByteArray(ret.getDataPointer(), nret); return ret; }
int PKCS11_private_encrypt(int flen, const unsigned char *from, unsigned char *to, PKCS11_KEY * key, int padding) { PKCS11_KEY_private *priv; PKCS11_SLOT *slot; PKCS11_CTX *ctx; CK_SESSION_HANDLE session; CK_MECHANISM mechanism; int rv; int sigsize; CK_ULONG ck_sigsize; if (key == NULL) return -1; sigsize=PKCS11_get_key_size(key); ck_sigsize=sigsize; memset(&mechanism, 0, sizeof(mechanism)); switch (padding) { case RSA_NO_PADDING: mechanism.mechanism = CKM_RSA_X_509; break; case RSA_PKCS1_PADDING: if ((flen + RSA_PKCS1_PADDING_SIZE) > sigsize) { return -1; /* the size is wrong */ } mechanism.mechanism = CKM_RSA_PKCS; break; default: printf("pkcs11 engine: only RSA_NO_PADDING or RSA_PKCS1_PADDING allowed so far\n"); return -1; } ctx = KEY2CTX(key); priv = PRIVKEY(key); slot = TOKEN2SLOT(priv->parent); CHECK_KEY_FORK(key); session = PRIVSLOT(slot)->session; pkcs11_w_lock(PRIVSLOT(slot)->lockid); /* API is somewhat fishy here. *siglen is 0 on entry (cleared * by OpenSSL). The library assumes that the memory passed * by the caller is always big enough */ rv = CRYPTOKI_call(ctx, C_SignInit(session, &mechanism, priv->object)) || CRYPTOKI_call(ctx, C_Sign(session, (CK_BYTE *) from, flen, to, &ck_sigsize)); pkcs11_w_unlock(PRIVSLOT(slot)->lockid); if (rv) { PKCS11err(PKCS11_F_PKCS11_RSA_SIGN, pkcs11_map_err(rv)); return -1; } if ((unsigned)sigsize != ck_sigsize) return -1; return sigsize; }