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