--- a/.gear/pam_pkcs11.spec +++ a/.gear/pam_pkcs11.spec @@ -2,7 +2,7 @@ Name: pam_pkcs11 Version: 0.6.9 -Release: alt2.M70T.0.M70C.1 +Release: alt2.M70T.1.elvis.1 Summary: PKCS #11 PAM Module and Login Tools Group: System/Base @@ -20,6 +20,8 @@ Patch6: %name-%version-option-ask_pin.patch Patch70: use-autoconf-2.68.patch +Patch80: %name-%version-gost-elvis.patch + BuildRequires: docbook-style-xsl flex libldap-devel libpam-devel libpcsclite-devel libssl-devel xsltproc BuildRequires: doxygen BuildRequires: docbook-dtds @@ -75,6 +77,7 @@ as a separate package. %patch6 -p1 %patch70 -p1 +%patch80 -p1 # fixup configs sed -i -e ' @@ -157,6 +160,10 @@ rm %buildroot/%_lib/*/*.la /%_lib/%name/ldap_mapper.so %changelog +* Fri Jan 27 2017 Max Kosmach 0.6.9-alt2.M70T.1.elvis.1 +- Add support for GOST certificates + + * Tue Nov 22 2016 Ivan Zakharyaschev 0.6.9-alt2.M70T.0.M70C.1 - Build for c7 --- a/.gear/rules +++ a/.gear/rules @@ -9,3 +9,4 @@ diff: @name@-@version@:. @name@-@version@-ru.po:. name=@name@-@version@-ru.po.pa diff: @name@-@version@:. @name@-@version@-buffer:. name=@name@-@version@-buffer.patch diff: @name@-@version@-buffer:. @name@-@version@-ask-pin-later:. name=@name@-@version@-ask-pin-later.patch diff: @name@-@version@-ask-pin-later:. @name@-@version@-ask-pin-later-with-option-ask_pin:. name=@name@-@version@-option-ask_pin.patch +diff: @name@-@version@-c7:. e6719bdc84366f615ad5cb6d714f881a38f8162a:. name=@name@-@version@-gost-elvis.patch --- a/.gear/tags/list +++ a/.gear/tags/list @@ -6,3 +6,4 @@ 4198e4bc3818a76e9fa71842a847a356f9873749 pam_pkcs11-0.6.9-buffer 9a268c67b78e8a668d26a37b41bd2db39675914f pam_pkcs11-0.6.9-ask-pin-later 8247217c608dee7c3d429fce61068c4cde7df07e pam_pkcs11-0.6.9-ask-pin-later-with-option-ask_pin +7dd57ca145e86bce86957c65594f0aed4036cee1 pam_pkcs11-0.6.9-c7 --- a/po/ru.po +++ a/po/ru.po @@ -36,7 +36,7 @@ msgstr "" #: src/pam_pkcs11/pam_pkcs11.c:387 msgid "Error 2306: No suitable token available" -msgstr "" +msgstr "Ошибка 2306: Нет подходящего токена" #: src/pam_pkcs11/pam_pkcs11.c:401 #, c-format @@ -49,11 +49,11 @@ msgstr "Пожалуйста, вставьте токен." #: src/pam_pkcs11/pam_pkcs11.c:422 msgid "Error 2308: No smartcard found" -msgstr "" +msgstr "Ошибка 2308: Не найдена смарт-карта" #: src/pam_pkcs11/pam_pkcs11.c:449 msgid "Error 2310: No smartcard found" -msgstr "" +msgstr "Ошибка 2310: Не найдена смарт-карта" #: src/pam_pkcs11/pam_pkcs11.c:459 #, c-format @@ -93,31 +93,31 @@ msgstr "" #: src/pam_pkcs11/pam_pkcs11.c:553 msgid "Error 2320: Wrong smartcard PIN" -msgstr "" +msgstr "Ошибка 2320: Неверный ПИН" #: src/pam_pkcs11/pam_pkcs11.c:565 msgid "Error 2322: No certificate found" -msgstr "" +msgstr "Ошибка 2322: Не найден сертификат" #: src/pam_pkcs11/pam_pkcs11.c:580 msgid "verifying certificate" -msgstr "" +msgstr "Проверка сертификата" #: src/pam_pkcs11/pam_pkcs11.c:593 msgid "Error 2324: Certificate has expired" -msgstr "" +msgstr "Ошибка 2324: Истек срок действия сертификата" #: src/pam_pkcs11/pam_pkcs11.c:597 msgid "Error 2326: Certificate not yet valid" -msgstr "" +msgstr "Ошибка 2326: Срок действия сертификата еще не наступил" #: src/pam_pkcs11/pam_pkcs11.c:601 msgid "Error 2328: Certificate signature invalid" -msgstr "" +msgstr "Ошибка 2328: Неверная подпись сертификата" #: src/pam_pkcs11/pam_pkcs11.c:605 msgid "Error 2330: Certificate invalid" -msgstr "" +msgstr "Ошибка 2330: Неверный сертификат" #: src/pam_pkcs11/pam_pkcs11.c:640 msgid "Error 2332: setting PAM userentry failed" @@ -125,15 +125,15 @@ msgstr "" #: src/pam_pkcs11/pam_pkcs11.c:656 msgid "Error 2334: No matching user" -msgstr "" +msgstr "Ошибка 2334: Нет подходящего пользователя" #: src/pam_pkcs11/pam_pkcs11.c:677 msgid "Error 2336: No matching certificate found" -msgstr "" +msgstr "Ошибка 2336: Нет подходящего сертификата" #: src/pam_pkcs11/pam_pkcs11.c:686 msgid "Checking signature" -msgstr "" +msgstr "Проверка подписи" #: src/pam_pkcs11/pam_pkcs11.c:706 msgid "Error 2338: Getting random value failed" @@ -141,11 +141,11 @@ msgstr "" #: src/pam_pkcs11/pam_pkcs11.c:720 msgid "Error 2340: Signing failed" -msgstr "" +msgstr "Ошибка 2340: Не удалось сформировать подпись" #: src/pam_pkcs11/pam_pkcs11.c:739 msgid "Error 2342: Verifying signature failed" -msgstr "" +msgstr "Ошибка 2342: Не удалось проверить подпись" #: src/pam_pkcs11/pam_pkcs11.c:886 msgid "Cannot change the password on your smart card." --- a/src/common/cert_vfy.c +++ a/src/common/cert_vfy.c @@ -491,16 +491,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); @@ -512,4 +524,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 --- a/src/common/cert_vfy.h +++ a/src/common/cert_vfy.h @@ -54,6 +54,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 @@ -81,6 +82,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_ */ --- a/src/common/pkcs11_lib.c +++ a/src/common/pkcs11_lib.c @@ -32,7 +32,7 @@ #include "error.h" #include "cert_info.h" #include "pkcs11_lib.h" - +#include /* * this functions is completely common between both implementation. @@ -979,6 +979,7 @@ int crypto_init(cert_policy *policy) { /* arg is ignored for OPENSSL */ (void)policy; + OPENSSL_config(NULL); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); return 0; @@ -1671,6 +1672,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 +1720,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 +1770,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); --- a/src/common/rsaref/pkcs11t.h +++ a/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; --- a/src/pam_pkcs11/pam_config.c +++ a/src/pam_pkcs11/pam_config.c @@ -91,6 +91,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); } @@ -192,6 +193,7 @@ static void parse_config_file(void) { configuration.policy.global_ca_policy=0; 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; @@ -207,6 +209,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); } @@ -340,6 +344,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; @@ -359,6 +364,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; } --- a/src/pam_pkcs11/pam_pkcs11.c +++ a/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) {