Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37478092
en ru br
Репозитории ALT
S:0.6.12.1-alt1
5.1: 0.6.1-alt5
www.altlinux.org/Changes

Группа :: Система/Основа
Пакет: 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) {
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin