Группа :: Система/Основа
Пакет: pam_pkcs11
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: pam_pkcs11-0.6.9-gost-support.patch
Скачать
Скачать
src/common/cert_vfy.c | 44 +++++++++++++++++++++++++++++++++++++++++---
src/common/cert_vfy.h | 3 +++
src/common/pkcs11_lib.c | 33 ++++++++++++++++++++++++++-------
src/common/rsaref/pkcs11t.h | 20 ++++++++++++++++++++
src/pam_pkcs11/pam_config.c | 8 ++++++++
src/pam_pkcs11/pam_pkcs11.c | 7 ++++++-
6 files changed, 104 insertions(+), 11 deletions(-)
diff --git a/src/common/cert_vfy.c b/src/common/cert_vfy.c
index 7efb0cb..41d3b64 100644
--- a/src/common/cert_vfy.c
+++ b/src/common/cert_vfy.c
@@ -481,16 +481,28 @@ int verify_signature(X509 * x509, unsigned char *data, int data_length,
int rv;
EVP_PKEY *pubkey;
EVP_MD_CTX *md_ctx = NULL;
-
+ const EVP_MD* md;
+ int nid;
/* get the public-key */
pubkey = X509_get_pubkey(x509);
if (pubkey == NULL) {
set_error("X509_get_pubkey() failed: %s", ERR_error_string(ERR_get_error(), NULL));
return -1;
}
- md_ctx = EVP_MD_CTX_new();
+
+ nid = OBJ_obj2nid(x509->cert_info->key->algor->algorithm);
+ if( NID_id_GostR3410_2001 == nid )
+ md = EVP_get_digestbyname("md_gost94");
+ else
+ md = EVP_sha1();
+ if (!md) {
+ set_error("unsupported key algorithm, nid: %d", nid);
+ return -1;
+ }
+
+ md_ctx = EVP_MD_CTX_create();
/* verify the signature */
- EVP_VerifyInit(md_ctx, EVP_sha1());
+ EVP_VerifyInit(md_ctx, md);
EVP_VerifyUpdate(md_ctx, data, data_length);
rv = EVP_VerifyFinal(md_ctx, signature, signature_length, pubkey);
EVP_PKEY_free(pubkey);
@@ -502,4 +514,30 @@ int verify_signature(X509 * x509, unsigned char *data, int data_length,
DBG("signature is valid");
return 0;
}
+
+int verify_eku_sc_logon(X509 * x509)
+{
+ static unsigned char id_kp_sc_logon[] = {0x2b, 6, 1, 4, 1, 0x82, 0x37, 20, 2, 2}; // 1.3.6.1.4.1.311.20.2.2
+ int rv = 0;
+ EXTENDED_KEY_USAGE* eku = X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL);
+ if( NULL != eku )
+ {
+ int i = 0, n = sk_ASN1_OBJECT_num(eku);
+ for( ; i < n; ++i )
+ {
+ ASN1_OBJECT* extobj = sk_ASN1_OBJECT_value( eku, i );
+ if( NULL == extobj )
+ continue;
+ if( sizeof(id_kp_sc_logon) == extobj->length
+ && 0 == memcmp(extobj->data, id_kp_sc_logon, sizeof(id_kp_sc_logon)) )
+ {
+ rv = 1;
+ break;
+ }
+ }
+ EXTENDED_KEY_USAGE_free(eku);
+ }
+ return rv;
+}
+
#endif
diff --git a/src/common/cert_vfy.h b/src/common/cert_vfy.h
index 657b212..335bc44 100644
--- a/src/common/cert_vfy.h
+++ b/src/common/cert_vfy.h
@@ -53,6 +53,7 @@ struct cert_policy_st {
const char *crl_dir;
const char *nss_dir;
int ocsp_policy;
+ int eku_sc_logon_policy;
};
#ifndef __CERT_VFY_C
@@ -80,6 +81,8 @@ CERTVFY_EXTERN int verify_certificate(X509 * x509, cert_policy *policy);
*/
CERTVFY_EXTERN int verify_signature(X509 * x509, unsigned char *data, int data_length, unsigned char *signature, int signature_length);
+CERTVFY_EXTERN int verify_eku_sc_logon(X509 * x509);
+
#undef CERTVFY_EXTERN
#endif /* __CERT_VFY_H_ */
diff --git a/src/common/pkcs11_lib.c b/src/common/pkcs11_lib.c
index 41b55d1..fd79837 100644
--- a/src/common/pkcs11_lib.c
+++ b/src/common/pkcs11_lib.c
@@ -32,7 +32,7 @@
#include "error.h"
#include "cert_info.h"
#include "pkcs11_lib.h"
-
+#include <openssl/conf.h>
/*
* this functions is completely common between both implementation.
@@ -1671,6 +1671,7 @@ getlist_error:
int get_private_key(pkcs11_handle_t *h, cert_object_t *cert) {
CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
CK_BBOOL key_sign = CK_TRUE;
+ CK_ATTRIBUTE attr;
CK_ATTRIBUTE key_template[] = {
{CKA_CLASS, &key_class, sizeof(key_class)}
,
@@ -1718,7 +1719,16 @@ int get_private_key(pkcs11_handle_t *h, cert_object_t *cert) {
}
cert->private_key = object;
- cert->key_type = CKK_RSA;
+ attr.type = CKA_KEY_TYPE;
+ attr.ulValueLen = sizeof(cert->key_type);
+ attr.pValue = &(cert->key_type);
+ rv = h->fl->C_GetAttributeValue(h->session, object, &attr,1);
+ if (rv != CKR_OK) {
+ set_error("C_GetAttributeValue() failed: 0x%08lX", rv);
+ return -1;
+ }
+
+ DBG1("C_GetAttributeValue keytype: %x",cert->key_type);
return 0;
@@ -1759,29 +1769,38 @@ int sign_value(pkcs11_handle_t *h, cert_object_t *cert, CK_BYTE *data,
case CKK_RSA:
mechanism.mechanism = CKM_RSA_PKCS;
break;
+ case CKK_GOSTR3410:
+ mechanism.mechanism = CKM_GOSTR3410_WITH_GOSTR3411;
+ break;
default:
set_error("unsupported key type %d", cert->type);
return -1;
}
/* compute hash-value */
- SHA1(data, length, &hash[15]);
- DBG5("hash[%ld] = [...:%02x:%02x:%02x:...:%02x]", sizeof(hash),
- hash[15], hash[16], hash[17], hash[sizeof(hash) - 1]);
+ if( CKK_RSA == cert->key_type ) {
+ SHA1(data, length, &hash[15]);
+ DBG5("hash[%ld] = [...:%02x:%02x:%02x:...:%02x]", sizeof(hash),
+ hash[15], hash[16], hash[17], hash[sizeof(hash) - 1]);
+ }
/* sign the token */
+ DBG2("C_SignInit: mech: %x, keytype: %x", mechanism.mechanism, cert->key_type);
rv = h->fl->C_SignInit(h->session, &mechanism, cert->private_key);
if (rv != CKR_OK) {
set_error("C_SignInit() failed: 0x%08lX", rv);
return -1;
}
*signature = NULL;
- *signature_length = 128;
+ *signature_length = 256;
while (*signature == NULL) {
*signature = malloc(*signature_length);
if (*signature == NULL) {
set_error("not enough free memory available");
return -1;
}
- rv = h->fl->C_Sign(h->session, hash, sizeof(hash), *signature, signature_length);
+ if( CKK_RSA == cert->key_type )
+ rv = h->fl->C_Sign(h->session, hash, sizeof(hash), *signature, signature_length);
+ else
+ rv = h->fl->C_Sign(h->session, data, length, *signature, signature_length);
if (rv == CKR_BUFFER_TOO_SMALL) {
/* increase signature length as long as it it to short */
free(*signature);
diff --git a/src/common/rsaref/pkcs11t.h b/src/common/rsaref/pkcs11t.h
index a80482b..37375ea 100644
--- a/src/common/rsaref/pkcs11t.h
+++ b/src/common/rsaref/pkcs11t.h
@@ -383,6 +383,11 @@ typedef CK_ULONG CK_KEY_TYPE;
#define CKK_CDMF 0x0000001E
#define CKK_AES 0x0000001F
+/* Elvis */
+#define CKK_GOSTR3410 0x00000030
+#define CKK_GOSTR3411 0x00000031
+#define CKK_GOST28147 0x00000032
+
#define CKK_VENDOR_DEFINED 0x80000000
@@ -774,6 +779,21 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
+/* Elvis */
+#define CKM_GOSTR3410_KEY_PAIR_GEN 0x00001200
+#define CKM_GOSTR3410 0x00001201
+#define CKM_GOSTR3410_WITH_GOSTR3411 0x00001202
+#define CKM_GOSTR3410_KEY_WRAP 0x00001203
+#define CKM_GOSTR3410_DERIVE 0x00001204
+#define CKM_GOSTR3411 0x00001210
+#define CKM_GOSTR3411_HMAC 0x00001211
+#define CKM_GOST28147_KEY_GEN 0x00001220
+#define CKM_GOST28147_ECB 0x00001221
+#define CKM_GOST28147 0x00001222
+#define CKM_GOST28147_MAC 0x00001223
+#define CKM_GOST28147_KEY_WRAP 0x00001224
+
+
#define CKM_VENDOR_DEFINED 0x80000000
typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
diff --git a/src/pam_pkcs11/pam_config.c b/src/pam_pkcs11/pam_config.c
index 9d2ad40..b8169c5 100644
--- a/src/pam_pkcs11/pam_config.c
+++ b/src/pam_pkcs11/pam_config.c
@@ -90,6 +90,7 @@ static void display_config (void) {
DBG1("crl_policy %d",configuration.policy.crl_policy);
DBG1("signature_policy %d",configuration.policy.signature_policy);
DBG1("ocsp_policy %d",configuration.policy.ocsp_policy);
+ DBG1("eku_sc_logon_policy %d",configuration.policy.eku_sc_logon_policy);
DBG1("err_display_time %d", configuration.err_display_time);
DBG1("ask_pin %d",configuration.ask_pin);
}
@@ -190,6 +191,7 @@ static void parse_config_file(void) {
configuration.policy.ocsp_policy=OCSP_NONE;
configuration.policy.ca_policy=0;
configuration.policy.signature_policy=0;
+ configuration.policy.eku_sc_logon_policy=0;
break;
} else if ( !strcmp(policy_list->data,"crl_auto") ) {
configuration.policy.crl_policy=CRLP_AUTO;
@@ -203,6 +205,8 @@ static void parse_config_file(void) {
configuration.policy.ca_policy=1;
} else if ( !strcmp(policy_list->data,"signature") ) {
configuration.policy.signature_policy=1;
+ } else if ( !strcmp(policy_list->data,"eku_sclogon") ) {
+ configuration.policy.eku_sc_logon_policy=1;
} else {
DBG1("Invalid CRL policy: %s",policy_list->data);
}
@@ -336,6 +340,7 @@ struct configuration_st *pk_configure( int argc, const char **argv ) {
configuration.policy.ca_policy=0;
configuration.policy.signature_policy=0;
configuration.policy.ocsp_policy=OCSP_NONE;
+ configuration.policy.eku_sc_logon_policy=0;
}
if (strstr(argv[i],"crl_online")) {
configuration.policy.crl_policy=CRLP_ONLINE;
@@ -355,6 +360,9 @@ struct configuration_st *pk_configure( int argc, const char **argv ) {
if (strstr(argv[i],"signature")) {
configuration.policy.signature_policy=1;
}
+ if (strstr(argv[i],"eku_sclogon")) {
+ configuration.policy.eku_sc_logon_policy=1;
+ }
continue;
}
diff --git a/src/pam_pkcs11/pam_pkcs11.c b/src/pam_pkcs11/pam_pkcs11.c
index 3cadabb..3503d1f 100644
--- a/src/pam_pkcs11/pam_pkcs11.c
+++ b/src/pam_pkcs11/pam_pkcs11.c
@@ -532,7 +532,12 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
if (!configuration->quiet) {
pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("verifying certificate"));
}
-
+ if (configuration->policy.eku_sc_logon_policy) {
+ if (!verify_eku_sc_logon(x509)) {
+ DBG("Certificate does not contain EKU Smart Card Logon");
+ continue; /* try next certificate */
+ }
+ }
/* verify certificate (date, signature, CRL, ...) */
rv = verify_certificate(x509,&configuration->policy);
if (rv < 0) {