/* Convert X.509 RSA/ECC/DSA/GOST public key into gcrypt internal sexp form. The resul is stored in *sexp, which must be freed (using ) when not needed anymore. *sexp must be NULL on entry, since it is overwritten. */ gpg_err_code_t keyutil_get_cert_sexp ( unsigned char *der, size_t len, gcry_sexp_t *p_sexp ) { gpg_err_code_t error = GPG_ERR_GENERAL; gcry_mpi_t n_mpi = NULL; gcry_mpi_t e_mpi = NULL; gcry_sexp_t sexp = NULL; gpg_error_t err; ksba_sexp_t p; ksba_cert_t ks_cert; size_t n; err = ksba_cert_new (&ks_cert); if (err) { error = GPG_ERR_BAD_KEY; goto cleanup; } err = ksba_cert_init_from_mem (ks_cert, der, len); if (err) { error = GPG_ERR_BAD_KEY; goto cleanup; } /* Get the public key from the certificate. */ p = ksba_cert_get_public_key (ks_cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { ksba_free (p); error = GPG_ERR_BAD_KEY; goto cleanup; } err = gcry_sexp_sscan ( p_sexp, NULL, p, n); if (err) { error = GPG_ERR_BAD_KEY; goto cleanup; } ksba_free (p); error = GPG_ERR_NO_ERROR; goto cleanup; #if 0 if ( (error = keyutil_get_cert_mpi ( der, len, &n_mpi, &e_mpi )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( gcry_sexp_build ( &sexp, NULL, "(public-key (rsa (n %m) (e %m)))", n_mpi, e_mpi ) ) { error = GPG_ERR_BAD_KEY; goto cleanup; } *p_sexp = sexp; sexp = NULL; error = GPG_ERR_NO_ERROR; #endif cleanup: if (n_mpi != NULL) { gcry_mpi_release (n_mpi); n_mpi = NULL; } if (e_mpi != NULL) { gcry_mpi_release (e_mpi); e_mpi = NULL; } if (sexp != NULL) { gcry_sexp_release (sexp); sexp = NULL; } return error; }
#if 0 … #endif
diff -u PKCS11_CSD_ORIG/command.c PKCS11_CSD/command.c --- PKCS11_CSD_ORIG/command.c 2018-07-19 16:25:20.778692015 +0300 +++ PKCS11_CSD/command.c 2018-07-19 16:25:10.238691435 +0300 @@ -1002,6 +1002,8 @@ { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 }; + CK_MECHANISM_TYPE mech_type = CKM_RSA_PKCS; + int pubkey_type; gpg_err_code_t error = GPG_ERR_GENERAL; pkcs11h_certificate_id_t cert_id = NULL; @@ -1021,8 +1023,18 @@ INJECT_SHA224, INJECT_SHA256, INJECT_SHA384, - INJECT_SHA512 + INJECT_SHA512, +/*For GOST*/ + INJECT_GOSTR3411_CP, + INJECT_STRIBOG256, + INJECT_STRIBOG512 } inject = INJECT_NONE; +#define NSSCK_VENDOR_PKCS11_RU_TEAM 0xd4321000 //0x80000000|0x54321000 +#define NSSCK_VENDOR_PKSC11_RU_TEAM NSSCK_VENDOR_PKCS11_RU_TEAM +#define CK_VENDOR_PKCS11_RU_TEAM_TC26 NSSCK_VENDOR_PKCS11_RU_TEAM +#define CKM_GOSTR3410 0x00001201 +// TC 26 +#define CKM_GOSTR3410_512 (CK_VENDOR_PKCS11_RU_TEAM_TC26 |0x006) if (data->data == NULL) { error = GPG_ERR_INV_DATA; @@ -1107,6 +1119,16 @@ else if (!strcmp(hash, "sha512") && data->size == 0x40) { inject = INJECT_SHA512; } + else if (!strcmp(hash, "gost3411_94") || !strcmp(hash, "gost3411_CP") || !strcmp(hash, "gostr3411_94") || !strcmp(hash, "gostr3411_CP")) { + inject = INJECT_GOSTR3411_CP; + } + else if (!strcmp(hash, "gost3411_12_256") || !strcmp(hash, "gostr3411_12_256") || !strcasecmp(hash, "stribog256")) { + inject = INJECT_STRIBOG256; + } + else if (!strcmp(hash, "gost3411_12_512") || !strcmp(hash, "gostr3411_12_512") || !strcasecmp(hash, "stribog512")) { + inject = INJECT_STRIBOG512; + } + else { common_log (LOG_DEBUG, "unsupported hash algo (hash=%s,size=%d)", hash, data->size); error = GPG_ERR_UNSUPPORTED_ALGORITHM; @@ -1169,6 +1191,23 @@ oid = sha512_prefix; oid_size = sizeof(sha512_prefix); break; +/* */ + case INJECT_GOSTR3411_CP: + oid = ""; + oid_size = 0; + mech_type = CKM_GOSTR3410; + break; + case INJECT_STRIBOG256: + oid = ""; + oid_size = 0; + mech_type = CKM_GOSTR3410; + break; + case INJECT_STRIBOG512: + oid = ""; + oid_size = 0; + mech_type = CKM_GOSTR3410_512; + break; + default: error = GPG_ERR_INV_DATA; goto cleanup; @@ -1232,7 +1271,7 @@ (error = common_map_pkcs11_error ( pkcs11h_certificate_signAny ( cert, - CKM_RSA_PKCS, + mech_type, _data->data, _data->size, NULL, @@ -1252,7 +1291,7 @@ (error = common_map_pkcs11_error ( pkcs11h_certificate_signAny ( cert, - CKM_RSA_PKCS, + mech_type, _data->data, _data->size, sig, @@ -1298,6 +1337,9 @@ return gpg_error (error); } +/* */ +#define CKM_GOSTR3410_KEY_WRAP 0x00001203 + /** Decrypt data (set by SETDATA) with certificate id in line. */ gpg_error_t cmd_pkdecrypt (assuan_context_t ctx, char *line) { @@ -1309,6 +1351,7 @@ int session_locked = 0; cmd_data_t *data = (cmd_data_t *)assuan_get_pointer (ctx); cmd_data_t _data; + CK_MECHANISM_TYPE mech_type; if ( data == NULL || @@ -1317,6 +1360,13 @@ error = GPG_ERR_INV_DATA; goto cleanup; } + if(memmem(data->data, data->size,"\x2A\x85\x03", 3)){ +/* */ + mech_type = CKM_GOSTR3410_KEY_WRAP; + } + else{ + mech_type = CKM_RSA_PKCS; + } /* * Guess.. taken from openpgp card implementation @@ -1376,7 +1426,7 @@ (error = common_map_pkcs11_error ( pkcs11h_certificate_decryptAny ( cert, - CKM_RSA_PKCS, + mech_type, _data.data, _data.size, NULL, @@ -1396,7 +1446,7 @@ (error = common_map_pkcs11_error ( pkcs11h_certificate_decryptAny ( cert, - CKM_RSA_PKCS, + mech_type, _data.data, _data.size, ptext, @@ -1591,6 +1641,29 @@ goto cleanup; } } + else if (!strcmp (line, "APPTYPE")) { + if ( + (error = assuan_write_status( + ctx, + "APPTYPE", + "NKS" + )) != GPG_ERR_NO_ERROR + ) { + goto cleanup; + } + } + else if (!strcmp (line, "NKS-VERSION")) { + if ( + (error = assuan_write_status( + ctx, + "NKS-VERSION", + "3" + )) != GPG_ERR_NO_ERROR + ) { + goto cleanup; + } + } + else if (!strcmp (line, "KEY-ATTR")) { int i; for (i=0;i<3;i++) { diff -u PKCS11_CSD_ORIG/keyutil.c PKCS11_CSD/keyutil.c --- PKCS11_CSD_ORIG/keyutil.c 2018-07-19 16:25:20.779692015 +0300 +++ PKCS11_CSD/keyutil.c 2018-07-19 16:51:48.934779338 +0300 @@ -45,6 +45,7 @@ typedef const unsigned char *my_openssl_d2i_t; #endif #endif +#include <ksba.h> gpg_err_code_t keyutil_get_cert_mpi ( @@ -193,10 +194,10 @@ return error; } -/** - Convert X.509 RSA public key into gcrypt internal sexp form. Only RSA - public keys are accepted at the moment. The resul is stored in *sexp, - which must be freed (using ) when not needed anymore. *sexp must be + +/* + Convert X.509 RSA/ECC/DSA/GOST public key into gcrypt internal sexp form. The resul is stored + in *sexp, which must be freed (using ) when not needed anymore. *sexp must be NULL on entry, since it is overwritten. */ gpg_err_code_t @@ -210,6 +211,40 @@ gcry_mpi_t e_mpi = NULL; gcry_sexp_t sexp = NULL; + gpg_error_t err; + ksba_sexp_t p; + ksba_cert_t ks_cert; + size_t n; + + err = ksba_cert_new (&ks_cert); + if (err) { + error = GPG_ERR_BAD_KEY; + goto cleanup; + } + err = ksba_cert_init_from_mem (ks_cert, der, len); + if (err) { + error = GPG_ERR_BAD_KEY; + goto cleanup; + } + /* Get the public key from the certificate. */ + p = ksba_cert_get_public_key (ks_cert); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + { + ksba_free (p); + error = GPG_ERR_BAD_KEY; + goto cleanup; + } + err = gcry_sexp_sscan ( p_sexp, NULL, p, n); + if (err) { + error = GPG_ERR_BAD_KEY; + goto cleanup; + } + ksba_free (p); + error = GPG_ERR_NO_ERROR; + goto cleanup; +#if 0 + if ( (error = keyutil_get_cert_mpi ( der, @@ -237,6 +272,7 @@ *p_sexp = sexp; sexp = NULL; error = GPG_ERR_NO_ERROR; +#endif cleanup:
export LIBS=" -lksba" #./configure --without-gnutls ./configure --without-openssl make
diff -u KSBA_ORIG/cms.c KSBA/cms.c --- KSBA_ORIG/cms.c 2013-03-15 23:26:38.000000000 +0400 +++ KSBA/cms.c 2018-07-19 08:24:48.774106713 +0300 @@ -1581,6 +1581,15 @@ Note that IDX is only used for consistency checks. */ +/* For GOST + r_sig = (sig-val + (gost + (r <mpi>) + (s <mpi>) + ) + (hash <name_hash>)) +*/ + gpg_error_t ksba_cms_set_sig_val (ksba_cms_t cms, int idx, ksba_const_sexp_t sigval) { @@ -1588,6 +1597,7 @@ unsigned long n; struct sig_val_s *sv, **sv_tail; int i; + int gost; if (!cms) return gpg_error (GPG_ERR_INV_VALUE); @@ -1615,6 +1625,11 @@ /* Break out the algorithm ID. */ if (!(n = snext (&s))) return gpg_error (GPG_ERR_INV_SEXP); + gost = 0; + if (n==4 && s[0] == 'g' && s[1] == 'o' && s[2] == 's' && s[3] == 't') { + /* kludge to allow "gost" to be passed as algorithm name */ + gost = 1; + } sv = xtrycalloc (1, sizeof *sv); if (!sv) @@ -1680,6 +1695,11 @@ s++; n--; } +if(gost){ + sv->value = xtrymalloc (n * 2); +} +else + sv->value = xtrymalloc (n); if (!sv->value) { @@ -1687,6 +1707,11 @@ xfree (sv); return gpg_error (GPG_ERR_ENOMEM); } +/*r s - -26*/ +if(gost == 1) + memcpy (sv->value + n, s, n); +else + memcpy (sv->value, s, n); sv->valuelen = n; s += n; @@ -1698,6 +1723,84 @@ return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* but may also be an invalid one */ } s++; +if(gost == 1){ + unsigned char sh[30]; + + if (*s != '(') + { + xfree (sv->algo); + xfree (sv); + return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP); + } + s++; + if (!(n = snext (&s))) + { + xfree (sv->algo); + xfree (sv); + return gpg_error (GPG_ERR_INV_SEXP); + } + + s += n; /* ignore the name of the parameter */ + + if (!digitp(s)) + { + xfree (sv->algo); + xfree (sv); + /* May also be an invalid S-EXP. */ + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + } + if (!(n = snext (&s))) + { + xfree (sv->algo); + xfree (sv); + return gpg_error (GPG_ERR_INV_SEXP); + } + + if (n > 1 && !*s) + { /* We might have a leading zero due to the way we encode + MPIs - this zero should not go into the OCTECT STRING. */ + s++; + n--; + } +/*r s - -26*/ + memcpy (sv->value, s, n); + sv->valuelen += n; + s += n; + + if ( *s != ')' && s[1] != ')' && s[2] != '(' ) + { + xfree (sv->value); + xfree (sv->algo); + xfree (sv); + return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* but may also be an invalid one */ + } + s++;s++;s++; + if (!(n = snext (&s))) + { + xfree (sv->algo); + xfree (sv); + return gpg_error (GPG_ERR_INV_SEXP); + } + s += n; + if (!(n = snext (&s))) + { + xfree (sv->algo); + xfree (sv); + return gpg_error (GPG_ERR_INV_SEXP); + } + strncpy(sh, s, n); + if(!strcmp(sh, "1.2.643.7.1.1.2.2") || !strcasecmp(sh, "stribog256")) + sv->algo = xtrystrdup ("1.2.643.7.1.1.1.1"); + else if(!strcmp(sh, "1.2.643.7.1.1.2.3") || !strcasecmp(sh, "stribog512")) + sv->algo = xtrystrdup ("1.2.643.7.1.1.1.2"); + else if(!strcmp(sh, "1.2.643.2.2.9") || !strcasecmp(sh, "gostr3411_CP")) + sv->algo = xtrystrdup ("1.2.643.2.2.19"); + else { + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + } + s += n; + +} /* fixme: end loop over parameters */ /* we need 2 closing parenthesis */ diff -u KSBA_ORIG/dn.c KSBA/dn.c --- KSBA_ORIG/dn.c 2016-08-22 11:40:58.000000000 +0300 +++ KSBA/dn.c 2018-06-26 19:24:32.000000000 +0300 @@ -48,6 +48,7 @@ 2 = David Chadwick, July 2003 <draft-ietf-pkix-dnstrings-02.txt> 3 = Peter Gutmann + 4 = tk26 */ const char *description; size_t oidlen; @@ -74,12 +75,17 @@ "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19", "0.9.2342.19200300.100.1.25" }, {"UID", 1, "userid", 10, "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01", "0.9.2342.19200300.100.1.1 " }, -{"EMAIL", 3, "emailAddress", 9, +{"E", 1, "emailAddress", 9, "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01", "1.2.840.113549.1.9.1" }, +/*oid- TK-26*/ +{"OGRN", 4, "OGRN", 5, "\x2a\x85\x03\x64\x01", "1.2.643.100.1" }, +{"INN", 4, "INN", 8, "\x2a\x85\x03\x03\x81\x03\x01\x01", "1.2.643.3.131.1.1" }, +{"SNILS", 4, "SNILS", 5, "\x2a\x85\x03\x64\x03", "1.2.643.100.3" }, +{"OGRNIP", 4, "OGRNIP", 5, "\x2a\x85\x03\x64\x05", "1.2.643.100.5" }, + { NULL } }; - #define N 0x00 #define P 0x01 static unsigned char charclasses[128] = { @@ -555,8 +561,8 @@ name = NULL; for (i=0; oid_name_tbl[i].name; i++) { - if (oid_name_tbl[i].source == 1 - && node->len == oid_name_tbl[i].oidlen +/* oid- DN */ + if (node->len == oid_name_tbl[i].oidlen && !memcmp (image+node->off+node->nhdr, oid_name_tbl[i].oid, node->len)) { @@ -604,6 +610,9 @@ case TYPE_UTF8_STRING: append_utf8_value (image+node->off+node->nhdr, node->len, sb); break; +/* NUMERIC_STRING*/ + case TYPE_NUMERIC_STRING: + case TYPE_PRINTABLE_STRING: case TYPE_IA5_STRING: /* we assume that wrong encodings are latin-1 */ diff -u KSBA_ORIG/keyinfo.c KSBA/keyinfo.c --- KSBA_ORIG/keyinfo.c 2015-10-28 13:41:48.000000000 +0300 +++ KSBA/keyinfo.c 2018-07-19 09:03:27.936234230 +0300 @@ -45,7 +45,6 @@ #include "convert.h" #include "ber-help.h" - /* Constants used for the public key algorithms. */ typedef enum { @@ -98,6 +97,19 @@ "1.2.840.10045.2.1", /* ecPublicKey */ "\x2a\x86\x48\xce\x3d\x02\x01", 7, 1, PKALGO_ECC, "ecc", "q", "\x80" }, +/*oid- - */ + { /* GOST3410-2001 */ + "1.2.643.2.2.19", /* gostPublicKey-2001 */ + "\x2a\x85\x03\x02\x02\x13", 6, + 1, PKALGO_ECC, "ecc", "q", "\x80" }, + { /* GOST3410-2012-256 */ + "1.2.643.7.1.1.1.1", /* gostPublicKey-2012-256 */ + "\x2a\x85\x03\x07\x01\x01\x01\x01", 8, + 1, PKALGO_ECC, "ecc", "q", "\x80" }, + { /* GOST3410-2012-512 */ + "1.2.643.7.1.1.1.2", /* gostPublicKey-2012-512 */ + "\x2a\x85\x03\x07\x01\x01\x01\x02", 8, + 1, PKALGO_ECC, "ecc", "q", "\x80" }, {NULL} }; @@ -209,6 +221,31 @@ "1.3.36.3.4.3.2.2", /* sigS_ISO9796-2rndWithrsa_ripemd160 */ "\x2B\x24\x03\x04\x03\x02\x02", 7, 0, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "rmd160" }, + { /* GOST3410-2001 */ + "1.2.643.2.2.19", /* gostPublicKey-2001 */ + "\x2a\x85\x03\x02\x02\x13", 6, + 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "gostr3411_CP" }, + { /* GOST3410-2012-256 */ + "1.2.643.7.1.1.1.1", /* gostPublicKey-2012-256 */ + "\x2a\x85\x03\x07\x01\x01\x01\x01", 8, + 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog256"}, + { /* GOST3410-2012-512 */ + "1.2.643.7.1.1.1.2", /* gostPublicKey-2012-512 */ + "\x2a\x85\x03\x07\x01\x01\x01\x02", 8, + 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog512"}, + + { /* GOST3411-2012-256 */ + "1.2.643.7.1.1.3.2", /* STRIBOG256 */ + "\x2a\x85\x03\x07\x01\x01\x03\x02", 8, + 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog256" }, + { /* GOST3411-2012-512 */ + "1.2.643.7.1.1.3.3", /* STRIBOG512 */ + "\x2a\x85\x03\x07\x01\x01\x03\x03", 8, + 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "stribog512" }, + { /* GOST3410-2001-Signature */ + "1.2.643.2.2.3", /* gosrPublicKey-2001 avec signature */ + "\x2a\x85\x03\x02\x02\x03", 6, + 1, PKALGO_ECC, "gost", "s", "\x80", NULL, NULL, "gostr3411_CP" }, {NULL} }; @@ -218,6 +255,20 @@ "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */ "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", 9, 1, PKALGO_RSA, "rsa", "a", "\x82" }, +/*oid- - */ + { + "1.2.643.2.2.19", /*GOST R34.10-2001 */ + "\x2A\x85\x03\x02\x02\x13", 6, + 1, PKALGO_ECC, "ecc", "a", "\x80" }, + { + "1.2.643.7.1.1.1.1", /*GOST R34.10-2012-256 */ + "\x2A\x85\x03\x07\x01\x01\x01\x01", 8, + 1, PKALGO_ECC, "ecc", "a", "\x80" }, + { + "1.2.643.7.1.1.1.2", /*GOST R34.10-2012-512 */ + "\x2A\x85\x03\x07\x01\x01\x01\x02", 8, + 1, PKALGO_ECC, "ecc", "a", "\x80" }, + {NULL} }; @@ -267,6 +318,13 @@ { "1.2.643.2.2.35.1", "GOST2001-CryptoPro-A" }, { "1.2.643.2.2.35.2", "GOST2001-CryptoPro-B" }, { "1.2.643.2.2.35.3", "GOST2001-CryptoPro-C" }, +/* oid- 34.10-2001/2012*/ +// "GOST2001-CryptoPro-XchA" + { "1.2.643.2.2.36.0", "GOST2001-CryptoPro-A" }, +// "GOST2001-CryptoPro-XchB" + { "1.2.643.2.2.36.1", "GOST2001-CryptoPro-C" }, + + { "1.2.643.7.1.2.1.2.1", "GOST2012-tc26-A" }, { "1.2.643.7.1.2.1.2.2", "GOST2012-tc26-B" }, @@ -393,7 +451,8 @@ /* get the object identifier */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); - c = *der++; derlen--; + c = *der++; + derlen--; if ( c != 0x06 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not an OBJECT IDENTIFIER */ TLV_LENGTH(der); @@ -418,6 +477,7 @@ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; + if ( c == 0x05 ) { /*printf ("parameter: NULL \n"); the usual case */ @@ -471,6 +531,7 @@ else { /* printf ("parameter: with tag %02x - ignored\n", c); */ + TLV_LENGTH(der); seqlen -= der - startparm; /* skip the value */ @@ -692,6 +753,8 @@ const unsigned char *ctrl; const char *elem; struct stringbuf sb; + int gost_key; + char *parm_oid_hash = NULL; *r_string = NULL; @@ -701,6 +764,7 @@ c = *der++; derlen--; if ( c != 0x30 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */ + TLV_LENGTH(der); /* and now the inner part */ err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr, @@ -715,13 +779,36 @@ && !memcmp (der+off, pk_algo_table[algoidx].oid, len)) break; } + if (!pk_algo_table[algoidx].oid) return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); if (!pk_algo_table[algoidx].supported) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); +/* 1 - - */ + gost_key = !memcmp(pk_algo_table[algoidx].oidstring, "1.2.643", 7); if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID) parm_oid = ksba_oid_to_str (der+parm_off, parm_len); + else +/* - */ + if (parm_off && parm_len && parm_type == TYPE_SEQUENCE && gost_key && (*(der+parm_off + off - 2) == TYPE_OBJECT_ID)){ +/* oid curve -*/ + int len_hash; + int len_curve; + unsigned char* addr_hash; + unsigned char* addr_curve; + len_curve = (int) *(der+parm_off + off -1); + addr_curve = der+parm_off + off; + parm_oid = ksba_oid_to_str (addr_curve, len_curve); +/* oid -*/ + if( *(addr_curve + len_curve)== TYPE_OBJECT_ID) { + len_hash = (unsigned int) *(der+parm_off + off + len_curve + 1); + addr_hash = addr_curve + len_curve + 2; + parm_oid_hash = ksba_oid_to_str (addr_hash, len_hash); + } +/* oid -*/ + } + else if (parm_off && parm_len) { parmder = der + parm_off; @@ -762,6 +849,13 @@ put_stringbuf_sexp (&sb, "curve"); put_stringbuf_sexp (&sb, parm_oid); put_stringbuf (&sb, ")"); +/* oid- - */ + if(gost_key && parm_oid_hash) { + put_stringbuf (&sb, "("); + put_stringbuf_sexp (&sb, "hash"); + put_stringbuf_sexp (&sb, parm_oid_hash); + put_stringbuf (&sb, ")"); + } } /* If parameters are given and we have a description for them, parse @@ -851,6 +945,43 @@ put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; put_stringbuf_sexp (&sb, tmp); +/* TK-26*/ + if(gost_key){ + unsigned char pk[129]; + unsigned char *x; + unsigned char *y; + int len_pk; + int len_xy; + int i; + unsigned char c_inv; + int offset; + pk[0] = 0x04; + if(len == 131 || len == 66){ + offset = 0; + if(der[0] == 0x04 && der[1] & 0x80) + offset = 3; + else if(der[0] == 0x04 && der[1] & 0x40) + offset = 2; + len_pk = len - offset; + memcpy(&pk[1], der + offset, len_pk); + x = &pk[1]; + len_xy = len_pk / 2; + y = x + len_xy; +/*REVERT-INVERTIROVANIE*/ + for (i = 0; i < (len_xy/2); i++) { + c_inv = *(x + i); + *(x + i) = *(x + len_xy - i - 1); + *(x + len_xy - i - 1) = c_inv; + } + for (i = 0; i < (len_xy/2); i++) { + c_inv = y[i]; + y[i] = y[len_xy - i -1]; + y[len_xy - i - 1] = c_inv; + } + put_stringbuf_mem_sexp (&sb, pk , len_pk + 1); + } + } else + put_stringbuf_mem_sexp (&sb, der, len); der += len; derlen -= len; @@ -1606,6 +1737,7 @@ const unsigned char *ctrl; const char *elem; struct stringbuf sb; + int gost_sign; /* FIXME: The entire function is very similar to keyinfo_to_sexp */ *r_string = NULL; @@ -1615,7 +1747,6 @@ else algo_table = enc_algo_table; - err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr, NULL, NULL, NULL); if (err) @@ -1628,11 +1759,16 @@ && !memcmp (der+off, algo_table[algoidx].oid, len)) break; } + if (!algo_table[algoidx].oid) return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); + if (!algo_table[algoidx].supported) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); +/* oid-*/ + gost_sign = !memcmp(algo_table[algoidx].oidstring, "1.2.643", 7); + der += nread; derlen -= nread; @@ -1682,8 +1818,21 @@ put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; +/* , r , s */ + if(gost_sign == 1 && algo_table == sig_algo_table){ + put_stringbuf_sexp (&sb, "r"); + put_stringbuf_mem_sexp (&sb, der+(len/2), len/2); + put_stringbuf (&sb, ")"); + put_stringbuf (&sb, "("); + put_stringbuf_sexp (&sb, "s"); + put_stringbuf_mem_sexp (&sb, der, len/2); + } + else{ + put_stringbuf_sexp (&sb, tmp); put_stringbuf_mem_sexp (&sb, der, len); + } + der += len; derlen -= len; put_stringbuf (&sb, ")");
diff -u AGENT_ORIG/call-scd.c AGENT/call-scd.c --- AGENT_ORIG/call-scd.c 2017-05-15 15:13:22.000000000 +0300 +++ AGENT/call-scd.c 2018-07-19 09:27:36.904313900 +0300 @@ -806,6 +806,14 @@ case GCRY_MD_SHA256: return "--hash=sha256"; case GCRY_MD_SHA384: return "--hash=sha384"; case GCRY_MD_SHA512: return "--hash=sha512"; +/* 34.11-2001/2012*/ + case GCRY_MD_STRIBOG512: + return "--hash=stribog512"; + case GCRY_MD_STRIBOG256: + return "--hash=stribog256"; + case GCRY_MD_GOSTR3411_CP: + return "--hash=gostr3411_CP"; + default: return ""; } } @@ -884,6 +892,7 @@ else snprintf (line, sizeof line, "PKSIGN %s %s", hash_algo_option (mdalgo), keyid); + rc = assuan_transact (ctrl->scd_local->ctx, line, put_membuf_cb, &data, inq_needpin, &inqparm, @@ -901,6 +910,7 @@ } *r_buf = get_membuf (&data, r_buflen); + return unlock_scd (ctrl, 0); } diff -u AGENT_ORIG/divert-scd.c AGENT/divert-scd.c --- AGENT_ORIG/divert-scd.c 2017-04-03 18:13:56.000000000 +0300 +++ AGENT/divert-scd.c 2018-07-19 09:29:03.896318684 +0300 @@ -160,6 +160,17 @@ log_error ("no object identifier for algo %d\n", algo); return gpg_error (GPG_ERR_INTERNAL); } +/*-*/ + switch(algo) { + case GCRY_MD_STRIBOG512: + case GCRY_MD_STRIBOG256: + case GCRY_MD_GOSTR3411_CP: + case GCRY_MD_GOSTR3411_94: + asnlen = 0; + break; + default : + break; + } frame = xtrymalloc (asnlen + digestlen); if (!frame) @@ -423,6 +434,7 @@ (void)desc_text; rc = ask_for_card (ctrl, shadow_info, &kid); + if (rc) return rc; @@ -498,7 +510,7 @@ n = snext (&s); if (!n) return gpg_error (GPG_ERR_INV_SEXP); - if (smatch (&s, n, "rsa")) + if (smatch (&s, n, "rsa") || smatch (&s, n, "ecc")) { if (*s != '(') return gpg_error (GPG_ERR_UNKNOWN_SEXP); diff -u AGENT_ORIG/pksign.c AGENT/pksign.c --- AGENT_ORIG/pksign.c 2017-05-15 15:13:22.000000000 +0300 +++ AGENT/pksign.c 2018-07-19 09:30:28.771323350 +0300 @@ -328,6 +328,7 @@ int is_RSA = 0; int is_ECDSA = 0; int is_EdDSA = 0; + int is_ECGOST = 0; rc = agent_public_key_from_file (ctrl, ctrl->keygrip, &s_pkey); if (rc) @@ -345,6 +346,21 @@ is_RSA = 1; else if (key_type == GCRY_PK_ECDSA) is_ECDSA = 1; +/* -*/ + if (is_ECDSA) { + switch(ctrl->digest.algo) + { + case GCRY_MD_STRIBOG512: + case GCRY_MD_STRIBOG256: + case GCRY_MD_GOSTR3411_CP: + case GCRY_MD_GOSTR3411_94: + is_ECGOST = 1; + break; + default : + is_ECGOST = 0; + break; + } + } } { @@ -361,7 +377,7 @@ } if (rc) { - log_error ("smartcard signing failed: %s\n", gpg_strerror (rc)); + log_error ("agent_pksign_do: smartcard signing failed: %s\n", gpg_strerror (rc)); goto leave; } @@ -396,7 +412,8 @@ r_buflen = s_buflen = len/2; - if (*buf & 0x80) + if ((*buf & 0x80) && !is_ECGOST) + { r_buflen++; r_buf_allocated = xtrymalloc (r_buflen); @@ -409,8 +426,8 @@ } else r_buf = buf; + if ((*(buf + len/2) & 0x80) && !is_ECGOST) - if (*(buf + len/2) & 0x80) { s_buflen++; s_buf_allocated = xtrymalloc (s_buflen); @@ -427,6 +444,15 @@ else s_buf = buf + len/2; + if(is_ECGOST){ + rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(gost(r%b)(s%b))(hash %s))", + s_buflen, s_buf, + r_buflen, r_buf, + gcry_md_algo_name(ctrl->digest.algo)); + gcry_log_debugsxp ("SIG_VAL", s_sig); + } + else + rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(ecdsa(r%b)(s%b)))", r_buflen, r_buf, s_buflen, s_buf);
diff -u SM_ORIG/call-agent.c SM/call-agent.c --- SM_ORIG/call-agent.c 2017-04-03 18:13:56.000000000 +0300 +++ SM/call-agent.c 2018-07-19 09:37:08.411345324 +0300 @@ -234,6 +234,7 @@ rc = start_agent (ctrl); if (rc) return rc; + inq_parm.ctrl = ctrl; inq_parm.ctx = agent_ctx; @@ -313,6 +314,14 @@ case GCRY_MD_RMD160:hashopt = "--hash=rmd160"; break; case GCRY_MD_MD5: hashopt = "--hash=md5"; break; case GCRY_MD_SHA256:hashopt = "--hash=sha256"; break; +/*-*/ + case GCRY_MD_STRIBOG512: + hashopt = "--hash=stribog512"; break; + case GCRY_MD_STRIBOG256: + hashopt = "--hash=stribog256"; break; + case GCRY_MD_GOSTR3411_CP: + hashopt = "--hash=gostr3411_CP"; break; + default: return gpg_error (GPG_ERR_DIGEST_ALGO); } @@ -357,7 +366,20 @@ xfree (sigbuf); return 0; } - p = stpcpy (p, "(7:sig-val(3:rsa(1:s" ); +/* -*/ + switch(digestalgo) + { + case GCRY_MD_STRIBOG512: + case GCRY_MD_STRIBOG256: + case GCRY_MD_GOSTR3411_CP: + case GCRY_MD_GOSTR3411_94: + p = stpcpy (p, "(7:sig-val(3:ecc(1:s" ); + break; + default: + p = stpcpy (p, "(7:sig-val(3:rsa(1:s" ); + break; + } + sprintf (p, "%u:", (unsigned int)sigbuflen); p += strlen (p); memcpy (p, sigbuf, sigbuflen); diff -u SM_ORIG/certcheck.c SM/certcheck.c --- SM_ORIG/certcheck.c 2017-04-03 18:13:56.000000000 +0300 +++ SM/certcheck.c 2018-07-19 09:37:52.028347722 +0300 @@ -71,11 +71,13 @@ size_t nframe; unsigned char *frame; - if (pkalgo == GCRY_PK_DSA || pkalgo == GCRY_PK_ECDSA) + if (pkalgo == GCRY_PK_DSA || pkalgo == GCRY_PK_ECDSA || pkalgo == GCRY_PK_ECC) + { unsigned int qbits; - if ( pkalgo == GCRY_PK_ECDSA ) + if ( pkalgo == GCRY_PK_ECDSA || pkalgo == GCRY_PK_ECC) + qbits = gcry_pk_get_nbits (pkey); else qbits = get_dsa_qbits (pkey); @@ -169,7 +171,7 @@ memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; assert ( n == nframe ); } - if (DBG_CRYPTO) +// if (DBG_CRYPTO) { int j; log_debug ("encoded hash:"); @@ -177,6 +179,22 @@ log_printf (" %02X", frame[j]); log_printf ("\n"); } + int i; + for (i = 0; i < (nframe/2); i++) { + unsigned char c; + c = frame[i]; + frame[i] = frame[nframe - i -1]; + frame[nframe - i - 1] = c; + } + if (DBG_CRYPTO) + { + int j; + log_debug ("GOST encoded hash:"); + for (j=0; j < nframe; j++) + log_printf (" %02X", frame[j]); + log_printf ("\n"); + } + } gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe); xfree (frame); diff -u SM_ORIG/gpgsm.c SM/gpgsm.c --- SM_ORIG/gpgsm.c 2017-05-15 15:13:22.000000000 +0300 +++ SM/gpgsm.c 2018-07-19 09:38:33.277349990 +0300 @@ -471,6 +471,7 @@ { switch (algo) { + case GCRY_PK_ECC: case GCRY_PK_RSA: case GCRY_PK_ECDSA: return gcry_pk_test_algo (algo); @@ -1577,6 +1578,10 @@ opt.def_cipher_algoid = "1.2.392.200011.61.1.1.1.3"; else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA256") ) opt.def_cipher_algoid = "1.2.392.200011.61.1.1.1.4"; + else if (!strcmp (opt.def_cipher_algoid, "GOST28147") ) +// opt.def_cipher_algoid = "1.2.643.2.2.21"; + opt.def_cipher_algoid = "1.2.643.2.2.31.1"; + if (cmd != aGPGConfList) { diff -u SM_ORIG/keylist.c SM/keylist.c --- SM_ORIG/keylist.c 2017-05-15 15:13:22.000000000 +0300 +++ SM/keylist.c 2018-07-19 20:20:11.560466784 +0300 @@ -769,6 +769,42 @@ unsigned int nbits; algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits)); +/* -*/ + if(!strncasecmp(algoname, "ecc", 3)){ + gpg_error_t err; + ksba_sexp_t p; + size_t n; + gcry_sexp_t s_pkey, l2; + const char *str_hash; + const char *str_curve; + /* Get the public key from the issuer certificate. */ + p = ksba_cert_get_public_key (cert); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + err = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + ksba_free (p); +/* */ + l2 = gcry_sexp_find_token (s_pkey, "hash", 0); + str_hash = gcry_sexp_nth_string (l2, 1); + gcry_sexp_release (l2); +/* curve*/ + l2 = gcry_sexp_find_token (s_pkey, "curve", 0); + str_curve = gcry_sexp_nth_string (l2, 1); + gcry_sexp_release (l2); + gcry_sexp_release (s_pkey); + if(!memcmp(str_hash, "1.2.643.7", 9)){ +/* GOST R 34.10-2012-512 */ + es_fprintf (fp, " keyType: %u bit %s (Curve: %s))\n", + nbits, "GOST R 34.10-2012", str_curve); + } else if(!memcmp(str_hash, "1.2.643.2", 9)){ +/* GOST R 34.10-2012-246 */ + es_fprintf (fp, " keyType: %u bit %s (Curve: %s))\n", + nbits, "GOST R 34.10-2001", str_curve); + } else + es_fprintf (fp, " keyType: %u bit %s\n", + nbits, algoname? algoname:"?"); + } + else + es_fprintf (fp, " keyType: %u bit %s\n", nbits, algoname? algoname:"?"); } @@ -1118,6 +1154,42 @@ unsigned int nbits; algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits)); +/* -*/ + if(!strncasecmp(algoname, "ecc", 3)){ + gpg_error_t err; + ksba_sexp_t p; + size_t n; + gcry_sexp_t s_pkey, l2; + const char *str_hash; + const char *str_curve; + /* Get the public key from the issuer certificate. */ + p = ksba_cert_get_public_key (cert); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + err = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + ksba_free (p); +/* */ + l2 = gcry_sexp_find_token (s_pkey, "hash", 0); + str_hash = gcry_sexp_nth_string (l2, 1); + gcry_sexp_release (l2); +/* curve*/ + l2 = gcry_sexp_find_token (s_pkey, "curve", 0); + str_curve = gcry_sexp_nth_string (l2, 1); + gcry_sexp_release (l2); + gcry_sexp_release (s_pkey); + if(!memcmp(str_hash, "1.2.643.7", 9)){ +/* GOST R 34.10-2012-512 */ + es_fprintf (fp, " keyType: %u bit %s (Curve: %s))\n", + nbits, "GOST R 34.10-2012", str_curve); + } else if(!memcmp(str_hash, "1.2.643.2", 9)){ +/* GOST R 34.10-2012-246 */ + es_fprintf (fp, " keyType: %u bit %s (Curve: %s))\n", + nbits, "GOST R 34.10-2001", str_curve); + } else + es_fprintf (fp, " keyType: %u bit %s\n", + nbits, algoname? algoname:"?"); + } + else + es_fprintf (fp, " key type: %u bit %s\n", nbits, algoname? algoname:"?"); } diff -u SM_ORIG/sign.c SM/sign.c --- SM_ORIG/sign.c 2017-05-15 15:13:22.000000000 +0300 +++ SM/sign.c 2018-07-19 09:41:05.738358373 +0300 @@ -33,7 +33,41 @@ #include "keydb.h" #include "../common/i18n.h" +char *cert_get_digest_algo_from_pk(ksba_cert_t cert) { + gpg_error_t err; + ksba_sexp_t p; + size_t n; + gcry_sexp_t s_pubkey; + char buf[50]; + const char *s; + gcry_sexp_t h_pk; + + /* Get the public key from the certificate. */ + p = ksba_cert_get_public_key (cert); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + { + ksba_free (p); + return NULL; + } + err = gcry_sexp_sscan ( &s_pubkey, NULL, p, n); + ksba_free (p); + if (err) { + return NULL; + } + h_pk = gcry_sexp_find_token (s_pubkey, "hash", 0); + if (h_pk){ + s = gcry_sexp_nth_data (h_pk, 1, &n); + memcpy(buf, s, n); + buf[n] = '\0'; + gcry_sexp_release (s_pubkey); + gcry_sexp_release (h_pk); + return (strdup(buf)); + } else { + return NULL; + } +} /* Hash the data and return if something was hashed. Return -1 on error. */ static int @@ -301,8 +335,6 @@ return err; } - - /* Perform a sign operation. @@ -328,6 +360,8 @@ ksba_isotime_t signed_at; certlist_t cl; int release_signerlist = 0; + const unsigned char *shash; + size_t lshash; audit_set_type (ctrl->audit, AUDIT_TYPE_SIGN); @@ -435,8 +469,15 @@ } else { + oid = (char *)cert_get_digest_algo_from_pk(cl->cert); + if (oid == NULL || strncmp(oid, "1.2.643", 7)) + oid = ksba_cert_get_digest_algo (cl->cert); cl->hash_algo = oid ? gcry_md_map_name (oid) : 0; + if(oid != NULL && !strcmp(oid, "1.2.643.2.2.30.1")){ + cl->hash_algo = GCRY_MD_GOSTR3411_CP; + } + } switch (cl->hash_algo) { @@ -446,6 +487,15 @@ case GCRY_MD_SHA256: oid = "2.16.840.1.101.3.4.2.1"; break; case GCRY_MD_SHA384: oid = "2.16.840.1.101.3.4.2.2"; break; case GCRY_MD_SHA512: oid = "2.16.840.1.101.3.4.2.3"; break; + case GCRY_MD_STRIBOG256: /* GOST R 34.11-2012, 256 bit. */ + oid = "1.2.643.7.1.1.2.2"; break; + case GCRY_MD_STRIBOG512: /* GOST R 34.11-2012, 512 bit. */ + oid = "1.2.643.7.1.1.2.3"; break; + case GCRY_MD_GOSTR3411_CP: /* GOST R 34.11-94. */ + oid = "1.2.643.2.2.9"; break; + case GCRY_MD_GOSTR3411_94: /* GOST R 34.11-94. TK26 */ + oid = "1.2.643.2.2.9"; break; + /* case GCRY_MD_WHIRLPOOL: oid = "No OID yet"; break; */ case GCRY_MD_MD5: /* We don't want to use MD5. */
… scdaemon-program /usr/local/bin64/gnupg-pkcs11-scd pinentry-program /usr/bin/pinentry-qt …
# # /usr/local/lib64/libls11sw2016.so … # Comma-separated list of available provider names. Then set # attributes for each provider using the provider-[name]-attribute # syntax. providers mytokenpkcs11 provider-mytokenpkcs11-library /usr/local/lib64/libls11sw2016.so # , , ruTokenECP #provider-metokenpkcs11-library /usr/local/lib64/librutokenecp.so provider-mytokenpkcs11-cert-private …
bash-4.3$ gpg-agent --daemon gpg-agent[1196]: enabled debug flags: ipc gpg-agent: gpg - , , gpg-agent: secmem usage: 0/32768 bytes in 0 blocks bash-4.3$
Source: https://habr.com/ru/post/417735/
All Articles