Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2017 Red Hat, Inc.
5 : *
6 : * Author: Jakub Jelen <jjelen@redhat.com>
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU Lesser General Public License as
10 : * published by the Free Software Foundation; either version 2.1 of
11 : * the License, or (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful, but
14 : * WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : * Lesser General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU Lesser General Public
19 : * License along with this program; if not, see
20 : * <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "config.h"
24 :
25 : #include "gkm-crypto.h"
26 : #include "gkm-ecdsa-mechanism.h"
27 : #include "gkm-session.h"
28 : #include "gkm-sexp.h"
29 : #include "gkm-sexp-key.h"
30 :
31 : #include "egg/egg-libgcrypt.h"
32 : #include "egg/egg-secure-memory.h"
33 :
34 : /* ----------------------------------------------------------------------------
35 : * PUBLIC
36 : */
37 :
38 : CK_RV
39 1 : gkm_ecdsa_mechanism_sign (gcry_sexp_t sexp, CK_BYTE_PTR data, CK_ULONG n_data,
40 : CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
41 : {
42 : gcry_sexp_t ssig, splain;
43 : gcry_error_t gcry;
44 : CK_ULONG size, key_bytes, key_bits;
45 : CK_RV rv;
46 :
47 1 : g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
48 1 : g_return_val_if_fail (n_signature, CKR_ARGUMENTS_BAD);
49 1 : g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
50 :
51 : /* If no output, then don't process */
52 1 : key_bits = gcry_pk_get_nbits(sexp);
53 1 : key_bytes = (key_bits + 7)/8;
54 1 : if (!signature) {
55 0 : *n_signature = key_bytes * 2;
56 0 : return CKR_OK;
57 1 : } else if (*n_signature < (key_bytes * 2)) {
58 0 : *n_signature = key_bytes * 2;
59 0 : return CKR_BUFFER_TOO_SMALL;
60 : }
61 :
62 : /* Prepare the input s-expression */
63 1 : gcry = gcry_sexp_build (&splain, NULL, "(data (flags raw) (value %b))",
64 : n_data, data);
65 1 : g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
66 :
67 : /* Do the magic */
68 1 : gcry = gcry_pk_sign (&ssig, splain, sexp);
69 1 : gcry_sexp_release (splain);
70 :
71 : /* TODO: Certain codes should be returned (data too big etc... ) */
72 1 : if (gcry) {
73 0 : g_message ("signing of the data failed: %s", gcry_strerror (gcry));
74 0 : return CKR_FUNCTION_FAILED;
75 : }
76 :
77 : /* signature consists of two mpint values concatenated */
78 1 : size = key_bytes;
79 1 : rv = gkm_crypto_sexp_to_data (ssig, key_bits, signature, &size, NULL, "ecdsa", "r", NULL);
80 1 : if (rv == CKR_OK) {
81 1 : g_return_val_if_fail (size == key_bytes, CKR_GENERAL_ERROR);
82 1 : rv = gkm_crypto_sexp_to_data (ssig, key_bits, signature + key_bytes, &size, NULL, "ecdsa", "s", NULL);
83 1 : if (rv == CKR_OK) {
84 1 : g_return_val_if_fail (size == key_bytes, CKR_GENERAL_ERROR);
85 1 : *n_signature = key_bytes * 2;
86 : }
87 : }
88 :
89 1 : gcry_sexp_release (ssig);
90 1 : return rv;
91 : }
92 :
93 : CK_RV
94 1 : gkm_ecdsa_mechanism_verify (gcry_sexp_t sexp, CK_BYTE_PTR data, CK_ULONG n_data,
95 : CK_BYTE_PTR signature, CK_ULONG n_signature)
96 : {
97 : gcry_sexp_t ssig, splain;
98 : gcry_error_t gcry;
99 : CK_ULONG key_bytes;
100 :
101 1 : g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
102 1 : g_return_val_if_fail (signature, CKR_ARGUMENTS_BAD);
103 1 : g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
104 :
105 1 : key_bytes = gcry_pk_get_nbits(sexp)/8;
106 1 : if (n_signature != key_bytes*2)
107 0 : return CKR_SIGNATURE_LEN_RANGE;
108 :
109 : /* Prepare the input s-expressions */
110 1 : gcry = gcry_sexp_build (&splain, NULL, "(data (flags raw) (value %b))",
111 : n_data, data);
112 1 : g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
113 :
114 1 : gcry = gcry_sexp_build (&ssig, NULL, "(sig-val (ecdsa (r %b) (s %b)))",
115 : key_bytes, signature, key_bytes, signature + key_bytes);
116 1 : g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
117 :
118 : /* Do the magic */
119 1 : gcry = gcry_pk_verify (ssig, splain, sexp);
120 1 : gcry_sexp_release (splain);
121 1 : gcry_sexp_release (ssig);
122 :
123 : /* TODO: See if any other codes should be mapped */
124 1 : if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) {
125 0 : return CKR_SIGNATURE_INVALID;
126 1 : } else if (gcry) {
127 0 : g_message ("verifying of the data failed: %s", gcry_strerror (gcry));
128 0 : return CKR_FUNCTION_FAILED;
129 : }
130 :
131 1 : return CKR_OK;
132 : }
133 :
|