summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2016-10-21 17:05:38 +0300
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2018-06-23 12:20:15 +0300
commit4bd42751adc13b47bcd2934112a93c6252404a43 (patch)
tree2a35e480f6c71cd1c784cffe593353450de74afd /lib
parentd2d448d5e072eb14c7e4f5c9bd634c5ab138d7c9 (diff)
downloadgnutls-4bd42751adc13b47bcd2934112a93c6252404a43.tar.gz
Add few functions to support basic operations with GOST public keys
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/includes/gnutls/crypto.h3
-rw-r--r--lib/includes/gnutls/gnutls.h.in7
-rw-r--r--lib/libgnutls.map5
-rw-r--r--lib/mpi.c25
-rw-r--r--lib/mpi.h1
-rw-r--r--lib/pk.c167
-rw-r--r--lib/pk.h11
-rw-r--r--lib/x509/common.c87
-rw-r--r--lib/x509/common.h7
9 files changed, 313 insertions, 0 deletions
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index 947e25caf9..f20d3463bb 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -247,6 +247,9 @@ gnutls_decode_ber_digest_info(const gnutls_datum_t * info,
int gnutls_decode_rs_value(const gnutls_datum_t * sig_value, gnutls_datum_t *r, gnutls_datum_t *s);
int gnutls_encode_rs_value(gnutls_datum_t * sig_value, const gnutls_datum_t * r, const gnutls_datum_t * s);
+int gnutls_encode_gost_rs_value(gnutls_datum_t * sig_value, const gnutls_datum_t * r, const gnutls_datum_t *s);
+int gnutls_decode_gost_rs_value(const gnutls_datum_t * sig_value, gnutls_datum_t * r, gnutls_datum_t * s);
+
/* *INDENT-OFF* */
#ifdef __cplusplus
}
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 66043925e1..7a0a63188d 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1180,6 +1180,11 @@ const char *
const char *gnutls_sign_get_oid(gnutls_sign_algorithm_t sign) __GNUTLS_CONST__;
+const char *
+ gnutls_gost_paramset_get_name(gnutls_gost_paramset_t param) __GNUTLS_CONST__;
+const char *
+ gnutls_gost_paramset_get_oid(gnutls_gost_paramset_t param) __GNUTLS_CONST__;
+
size_t
gnutls_cipher_get_key_size(gnutls_cipher_algorithm_t algorithm) __GNUTLS_CONST__;
size_t
@@ -1237,6 +1242,8 @@ gnutls_sign_algorithm_t
gnutls_oid_to_sign(const char *oid) __GNUTLS_CONST__;
gnutls_ecc_curve_t
gnutls_oid_to_ecc_curve(const char *oid) __GNUTLS_CONST__;
+gnutls_gost_paramset_t
+ gnutls_oid_to_gost_paramset(const char *oid) __GNUTLS_CONST__;
/* list supported algorithms */
const gnutls_ecc_curve_t *
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index f95fe0a846..6d81cf8b9c 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1221,6 +1221,11 @@ GNUTLS_3_6_3
gnutls_pkcs11_obj_get_ptr;
gnutls_session_ticket_send;
gnutls_aead_cipher_encryptv;
+ gnutls_gost_paramset_get_name;
+ gnutls_gost_paramset_get_oid;
+ gnutls_oid_to_gost_paramset;
+ gnutls_decode_gost_rs_value;
+ gnutls_encode_gost_rs_value;
} GNUTLS_3_6_2;
GNUTLS_FIPS140_3_4 {
diff --git a/lib/mpi.c b/lib/mpi.c
index 5dbcfb4069..083afe0fa7 100644
--- a/lib/mpi.c
+++ b/lib/mpi.c
@@ -270,6 +270,31 @@ _gnutls_mpi_dprint_size(const bigint_t a, gnutls_datum_t * dest,
return 0;
}
+/* like _gnutls_mpi_dprint_size, but prints into preallocated byte buffer */
+int
+_gnutls_mpi_bprint_size(const bigint_t a, uint8_t *buf, size_t size)
+{
+ int result;
+ size_t bytes = 0;
+
+ result = _gnutls_mpi_print(a, NULL, &bytes);
+ if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ return gnutls_assert_val(result);
+
+ if (bytes <= size) {
+ unsigned i;
+ size_t diff = size - bytes;
+
+ for (i = 0; i < diff; i++)
+ buf[i] = 0;
+ result = _gnutls_mpi_print(a, &buf[diff], &bytes);
+ } else {
+ result = _gnutls_mpi_print(a, buf, &bytes);
+ }
+
+ return result;
+}
+
/* Flags for __gnutls_x509_read_int() and __gnutls_x509_write_int */
#define GNUTLS_X509_INT_OVERWRITE (1 << 0)
#define GNUTLS_X509_INT_LE (1 << 1)
diff --git a/lib/mpi.h b/lib/mpi.h
index 2715c2ddc1..e9747e391d 100644
--- a/lib/mpi.h
+++ b/lib/mpi.h
@@ -83,6 +83,7 @@ int _gnutls_mpi_dprint_lz(const bigint_t a, gnutls_datum_t * dest);
int _gnutls_mpi_dprint(const bigint_t a, gnutls_datum_t * dest);
int _gnutls_mpi_dprint_size(const bigint_t a, gnutls_datum_t * dest,
size_t size);
+int _gnutls_mpi_bprint_size(const bigint_t a, uint8_t *buf, size_t size);
typedef int (*mpi_dprint_func)(const bigint_t a, gnutls_datum_t * dest);
diff --git a/lib/pk.c b/lib/pk.c
index 888cd64280..7ea7813142 100644
--- a/lib/pk.c
+++ b/lib/pk.c
@@ -295,6 +295,170 @@ _gnutls_decode_ber_rs_raw(const gnutls_datum_t * sig_value, gnutls_datum_t *r,
return 0;
}
+int
+_gnutls_encode_gost_rs(gnutls_datum_t * sig_value, bigint_t r, bigint_t s,
+ size_t intsize)
+{
+ uint8_t *data;
+ int result;
+
+ data = gnutls_malloc(intsize * 2);
+ if (data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if ((result = _gnutls_mpi_bprint_size(s, data, intsize)) < 0) {
+ gnutls_assert();
+ gnutls_free(data);
+ return result;
+ }
+
+ if ((result = _gnutls_mpi_bprint_size(r, data + intsize, intsize)) < 0) {
+ gnutls_assert();
+ gnutls_free(data);
+ return result;
+ }
+
+ sig_value->data = data;
+ sig_value->size = intsize * 2;
+
+ return 0;
+}
+
+int
+_gnutls_decode_gost_rs(const gnutls_datum_t * sig_value, bigint_t * r,
+ bigint_t * s)
+{
+ int ret;
+ unsigned halfsize = sig_value->size >> 1;
+
+ if (sig_value->size % 2 != 0) {
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ }
+
+ ret = _gnutls_mpi_init_scan(s, sig_value->data, halfsize);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ ret = _gnutls_mpi_init_scan(r, sig_value->data + halfsize, halfsize);
+ if (ret < 0) {
+ _gnutls_mpi_release(s);
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_encode_gost_rs_value:
+ * @sig_value: will hold a GOST signature according to RFC 4491 section 2.2.2
+ * @r: must contain the r value
+ * @s: must contain the s value
+ *
+ * This function will encode the provided r and s values, into binary
+ * representation according to RFC 4491 section 2.2.2, used for GOST R
+ * 34.10-2001 (and thus also for GOST R 34.10-2012) signatures.
+ *
+ * The output value should be deallocated using gnutls_free().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ *
+ * Since: 3.6.0
+ */
+int gnutls_encode_gost_rs_value(gnutls_datum_t * sig_value, const gnutls_datum_t * r, const gnutls_datum_t *s)
+{
+ uint8_t *data;
+ size_t intsize = r->size;
+
+ if (s->size != intsize) {
+ gnutls_assert();
+ return GNUTLS_E_ILLEGAL_PARAMETER;
+ }
+
+ data = gnutls_malloc(intsize * 2);
+ if (data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy(data, s->data, intsize);
+ memcpy(data + intsize, r->data, intsize);
+
+ sig_value->data = data;
+ sig_value->size = intsize * 2;
+
+ return 0;
+}
+
+/**
+ * gnutls_decode_gost_rs_value:
+ * @sig_value: will holds a GOST signature according to RFC 4491 section 2.2.2
+ * @r: will contain the r value
+ * @s: will contain the s value
+ *
+ * This function will decode the provided @sig_value, into @r and @s elements.
+ * See RFC 4491 section 2.2.2 for the format of signature value.
+ *
+ * The output values may be padded with a zero byte to prevent them
+ * from being interpreted as negative values. The value
+ * should be deallocated using gnutls_free().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ *
+ * Since: 3.6.0
+ */
+int gnutls_decode_gost_rs_value(const gnutls_datum_t * sig_value, gnutls_datum_t * r, gnutls_datum_t * s)
+{
+ int ret;
+ unsigned halfsize = sig_value->size >> 1;
+
+ if (sig_value->size % 2 != 0)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ ret = _gnutls_set_datum(s, sig_value->data, halfsize);
+ if (ret != 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_set_datum(r, sig_value->data + halfsize, halfsize);
+ if (ret != 0) {
+ _gnutls_free_datum(s);
+ return gnutls_assert_val(ret);
+ }
+
+ return 0;
+}
+
+gnutls_digest_algorithm_t _gnutls_gost_digest(gnutls_pk_algorithm_t pk)
+{
+ if (pk == GNUTLS_PK_GOST_01)
+ return GNUTLS_DIG_GOSTR_94;
+ else if (pk == GNUTLS_PK_GOST_12_256)
+ return GNUTLS_DIG_STREEBOG_256;
+ else if (pk == GNUTLS_PK_GOST_12_512)
+ return GNUTLS_DIG_STREEBOG_512;
+
+ gnutls_assert();
+
+ return GNUTLS_DIG_UNKNOWN;
+}
+
+gnutls_pk_algorithm_t _gnutls_digest_gost(gnutls_digest_algorithm_t digest)
+{
+ if (digest == GNUTLS_DIG_GOSTR_94)
+ return GNUTLS_PK_GOST_01;
+ else if (digest == GNUTLS_DIG_STREEBOG_256)
+ return GNUTLS_PK_GOST_12_256;
+ else if (digest == GNUTLS_DIG_STREEBOG_512)
+ return GNUTLS_PK_GOST_12_512;
+
+ gnutls_assert();
+
+ return GNUTLS_PK_UNKNOWN;
+}
+
/* some generic pk functions */
int _gnutls_pk_params_copy(gnutls_pk_params_st * dst,
@@ -972,6 +1136,9 @@ pk_prepare_hash(gnutls_pk_algorithm_t pk,
case GNUTLS_PK_DSA:
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_GOST_01:
+ case GNUTLS_PK_GOST_12_256:
+ case GNUTLS_PK_GOST_12_512:
break;
default:
gnutls_assert();
diff --git a/lib/pk.h b/lib/pk.h
index a6eb043333..a10a1c9dcc 100644
--- a/lib/pk.h
+++ b/lib/pk.h
@@ -70,6 +70,17 @@ _gnutls_decode_ber_rs_raw(const gnutls_datum_t * sig_value, gnutls_datum_t *r,
gnutls_datum_t *s);
int
+_gnutls_encode_gost_rs(gnutls_datum_t * sig_value, bigint_t r, bigint_t s,
+ size_t intsize);
+
+int
+_gnutls_decode_gost_rs(const gnutls_datum_t * sig_value, bigint_t * r,
+ bigint_t * s);
+
+gnutls_digest_algorithm_t _gnutls_gost_digest(gnutls_pk_algorithm_t pk);
+gnutls_pk_algorithm_t _gnutls_digest_gost(gnutls_digest_algorithm_t digest);
+
+int
encode_ber_digest_info(const mac_entry_st * e,
const gnutls_datum_t * digest,
gnutls_datum_t * output);
diff --git a/lib/x509/common.c b/lib/x509/common.c
index f4310d7e36..a446186625 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1813,3 +1813,90 @@ int _gnutls_check_if_sorted(gnutls_x509_crt_t * crt, int nr)
cleanup:
return ret;
}
+
+/**
+ * gnutls_gost_paramset_get_name:
+ * @param: is a GOST 28147 param set
+ *
+ * Convert a #gnutls_gost_paramset_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified GOST param set,
+ * or %NULL.
+ *
+ * Since: 3.6.3
+ **/
+const char *gnutls_gost_paramset_get_name(gnutls_gost_paramset_t param)
+{
+ switch(param) {
+ case GNUTLS_GOST_PARAMSET_TC26_Z:
+ return "TC26-Z";
+ case GNUTLS_GOST_PARAMSET_CP_A:
+ return "CryptoPro-A";
+ case GNUTLS_GOST_PARAMSET_CP_B:
+ return "CryptoPro-B";
+ case GNUTLS_GOST_PARAMSET_CP_C:
+ return "CryptoPro-C";
+ case GNUTLS_GOST_PARAMSET_CP_D:
+ return "CryptoPro-D";
+ default:
+ gnutls_assert();
+ return "Unknown";
+ }
+}
+
+/**
+ * gnutls_gost_paramset_get_oid:
+ * @param: is a GOST 28147 param set
+ *
+ * Convert a #gnutls_gost_paramset_t value to its object identifier.
+ *
+ * Returns: a string that contains the object identifier of the specified GOST
+ * param set, or %NULL.
+ *
+ * Since: 3.6.3
+ **/
+const char *gnutls_gost_paramset_get_oid(gnutls_gost_paramset_t param)
+{
+ switch(param) {
+ case GNUTLS_GOST_PARAMSET_TC26_Z:
+ return GOST28147_89_TC26Z_OID;
+ case GNUTLS_GOST_PARAMSET_CP_A:
+ return GOST28147_89_CPA_OID;
+ case GNUTLS_GOST_PARAMSET_CP_B:
+ return GOST28147_89_CPB_OID;
+ case GNUTLS_GOST_PARAMSET_CP_C:
+ return GOST28147_89_CPC_OID;
+ case GNUTLS_GOST_PARAMSET_CP_D:
+ return GOST28147_89_CPD_OID;
+ default:
+ gnutls_assert();
+ return NULL;
+ }
+}
+
+/**
+ * gnutls_oid_to_gost_paramset:
+ * @oid: is an object identifier
+ *
+ * Converts a textual object identifier to a #gnutls_gost_paramset_t value.
+ *
+ * Returns: a #gnutls_gost_paramset_get_oid of the specified GOST 28147
+ * param st, or %GNUTLS_GOST_PARAMSET_UNKNOWN on failure.
+ *
+ * Since: 3.6.3
+ **/
+gnutls_gost_paramset_t gnutls_oid_to_gost_paramset(const char *oid)
+{
+ if (!strcmp(oid, GOST28147_89_TC26Z_OID))
+ return GNUTLS_GOST_PARAMSET_TC26_Z;
+ else if (!strcmp(oid, GOST28147_89_CPA_OID))
+ return GNUTLS_GOST_PARAMSET_CP_A;
+ else if (!strcmp(oid, GOST28147_89_CPB_OID))
+ return GNUTLS_GOST_PARAMSET_CP_B;
+ else if (!strcmp(oid, GOST28147_89_CPC_OID))
+ return GNUTLS_GOST_PARAMSET_CP_C;
+ else if (!strcmp(oid, GOST28147_89_CPD_OID))
+ return GNUTLS_GOST_PARAMSET_CP_D;
+ else
+ return gnutls_assert_val(GNUTLS_GOST_PARAMSET_UNKNOWN);
+}
diff --git a/lib/x509/common.h b/lib/x509/common.h
index d5c368a7b9..637121c2ee 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -103,6 +103,13 @@
#define KRB5_PRINCIPAL_OID "1.3.6.1.5.2.2"
#define PKIX1_RSA_PSS_MGF1_OID "1.2.840.113549.1.1.8"
+#define GOST28147_89_OID "1.2.643.2.2.21"
+#define GOST28147_89_TC26Z_OID "1.2.643.7.1.2.5.1.1"
+#define GOST28147_89_CPA_OID "1.2.643.2.2.31.1"
+#define GOST28147_89_CPB_OID "1.2.643.2.2.31.2"
+#define GOST28147_89_CPC_OID "1.2.643.2.2.31.3"
+#define GOST28147_89_CPD_OID "1.2.643.2.2.31.4"
+
#define ASN1_NULL "\x05\x00"
#define ASN1_NULL_SIZE 2