]> git.ipfire.org Git - thirdparty/openssl.git/blame - engines/ccgost/gost_sign.c
Run util/openssl-format-source -v -c .
[thirdparty/openssl.git] / engines / ccgost / gost_sign.c
CommitLineData
a04549cc
DSH
1/**********************************************************************
2 * gost_sign.c *
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
5 * *
8711efb4 6 * Implementation of GOST R 34.10-94 signature algorithm *
a04549cc
DSH
7 * for OpenSSL *
8 * Requires OpenSSL 0.9.9 for compilation *
9 **********************************************************************/
10#include <string.h>
11#include <openssl/rand.h>
12#include <openssl/bn.h>
13#include <openssl/dsa.h>
f50ffd10 14#include <openssl/err.h>
a04549cc
DSH
15#include <openssl/evp.h>
16
926c41bd
DSH
17#include "gost_params.h"
18#include "gost_lcl.h"
a04549cc
DSH
19#include "e_gost_err.h"
20
926c41bd 21#ifdef DEBUG_SIGN
0f113f3e
MC
22void dump_signature(const char *message, const unsigned char *buffer,
23 size_t len)
24{
25 size_t i;
26 fprintf(stderr, "signature %s Length=%d", message, len);
27 for (i = 0; i < len; i++) {
28 if (i % 16 == 0)
29 fputc('\n', stderr);
30 fprintf(stderr, " %02x", buffer[i]);
31 }
32 fprintf(stderr, "\nEnd of signature\n");
33}
a04549cc 34
926c41bd 35void dump_dsa_sig(const char *message, DSA_SIG *sig)
0f113f3e
MC
36{
37 fprintf(stderr, "%s\nR=", message);
38 BN_print_fp(stderr, sig->r);
39 fprintf(stderr, "\nS=");
40 BN_print_fp(stderr, sig->s);
41 fprintf(stderr, "\n");
42}
a04549cc
DSH
43
44#else
45
0f113f3e
MC
46# define dump_signature(a,b,c)
47# define dump_dsa_sig(a,b)
a04549cc
DSH
48#endif
49
50/*
51 * Computes signature and returns it as DSA_SIG structure
52 */
0f113f3e
MC
53DSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
54{
55 BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL;
56 DSA_SIG *newsig = DSA_SIG_new();
57 BIGNUM *md = hashsum2bn(dgst);
58 /* check if H(M) mod q is zero */
59 BN_CTX *ctx = BN_CTX_new();
60 BN_CTX_start(ctx);
61 if (!newsig) {
62 GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE);
63 goto err;
64 }
65 tmp = BN_CTX_get(ctx);
66 k = BN_CTX_get(ctx);
67 tmp2 = BN_CTX_get(ctx);
68 BN_mod(tmp, md, dsa->q, ctx);
69 if (BN_is_zero(tmp)) {
70 BN_one(md);
71 }
72 do {
73 do {
74 /*
75 * Generate random number k less than q
76 */
77 BN_rand_range(k, dsa->q);
78 /* generate r = (a^x mod p) mod q */
79 BN_mod_exp(tmp, dsa->g, k, dsa->p, ctx);
80 if (!(newsig->r))
81 newsig->r = BN_new();
82 BN_mod(newsig->r, tmp, dsa->q, ctx);
83 }
84 while (BN_is_zero(newsig->r));
85 /* generate s = (xr + k(Hm)) mod q */
86 BN_mod_mul(tmp, dsa->priv_key, newsig->r, dsa->q, ctx);
87 BN_mod_mul(tmp2, k, md, dsa->q, ctx);
88 if (!newsig->s)
89 newsig->s = BN_new();
90 BN_mod_add(newsig->s, tmp, tmp2, dsa->q, ctx);
91 }
92 while (BN_is_zero(newsig->s));
93 err:
94 BN_free(md);
95 BN_CTX_end(ctx);
96 BN_CTX_free(ctx);
97 return newsig;
98}
a04549cc
DSH
99
100/*
101 * Packs signature according to Cryptocom rules
102 * and frees up DSA_SIG structure
103 */
1d97c843 104/*-
926c41bd 105int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
0f113f3e
MC
106 {
107 *siglen = 2*order;
108 memset(sig,0,*siglen);
109 store_bignum(s->r, sig,order);
110 store_bignum(s->s, sig + order,order);
111 dump_signature("serialized",sig,*siglen);
112 DSA_SIG_free(s);
113 return 1;
114 }
10f0c85c 115*/
a04549cc
DSH
116/*
117 * Packs signature according to Cryptopro rules
118 * and frees up DSA_SIG structure
119 */
0f113f3e
MC
120int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
121{
122 *siglen = 2 * order;
123 memset(sig, 0, *siglen);
124 store_bignum(s->s, sig, order);
125 store_bignum(s->r, sig + order, order);
126 dump_signature("serialized", sig, *siglen);
127 DSA_SIG_free(s);
128 return 1;
129}
a04549cc
DSH
130
131/*
132 * Verifies signature passed as DSA_SIG structure
133 *
926c41bd 134 */
a04549cc
DSH
135
136int gost_do_verify(const unsigned char *dgst, int dgst_len,
0f113f3e
MC
137 DSA_SIG *sig, DSA *dsa)
138{
139 BIGNUM *md, *tmp = NULL;
140 BIGNUM *q2 = NULL;
141 BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL;
142 BIGNUM *tmp2 = NULL, *tmp3 = NULL;
143 int ok;
144 BN_CTX *ctx = BN_CTX_new();
145
146 BN_CTX_start(ctx);
147 if (BN_cmp(sig->s, dsa->q) >= 1 || BN_cmp(sig->r, dsa->q) >= 1) {
148 GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
149 return 0;
150 }
151 md = hashsum2bn(dgst);
152
153 tmp = BN_CTX_get(ctx);
154 v = BN_CTX_get(ctx);
155 q2 = BN_CTX_get(ctx);
156 z1 = BN_CTX_get(ctx);
157 z2 = BN_CTX_get(ctx);
158 tmp2 = BN_CTX_get(ctx);
159 tmp3 = BN_CTX_get(ctx);
160 u = BN_CTX_get(ctx);
a04549cc 161
0f113f3e
MC
162 BN_mod(tmp, md, dsa->q, ctx);
163 if (BN_is_zero(tmp)) {
164 BN_one(md);
165 }
166 BN_copy(q2, dsa->q);
167 BN_sub_word(q2, 2);
168 BN_mod_exp(v, md, q2, dsa->q, ctx);
169 BN_mod_mul(z1, sig->s, v, dsa->q, ctx);
170 BN_sub(tmp, dsa->q, sig->r);
171 BN_mod_mul(z2, tmp, v, dsa->p, ctx);
172 BN_mod_exp(tmp, dsa->g, z1, dsa->p, ctx);
173 BN_mod_exp(tmp2, dsa->pub_key, z2, dsa->p, ctx);
174 BN_mod_mul(tmp3, tmp, tmp2, dsa->p, ctx);
175 BN_mod(u, tmp3, dsa->q, ctx);
176 ok = BN_cmp(u, sig->r);
177
178 BN_free(md);
179 BN_CTX_end(ctx);
180 BN_CTX_free(ctx);
181 if (ok != 0) {
182 GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH);
183 }
184 return (ok == 0);
185}
a04549cc
DSH
186
187/*
188 * Computes public keys for GOST R 34.10-94 algorithm
926c41bd 189 *
a04549cc
DSH
190 */
191int gost94_compute_public(DSA *dsa)
0f113f3e
MC
192{
193 /* Now fill algorithm parameters with correct values */
194 BN_CTX *ctx = BN_CTX_new();
195 if (!dsa->g) {
196 GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITALIZED);
197 return 0;
198 }
199 /* Compute public key y = a^x mod p */
200 dsa->pub_key = BN_new();
201 BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx);
202 BN_CTX_free(ctx);
203 return 1;
204}
a04549cc
DSH
205
206/*
207 * Fill GOST 94 params, searching them in R3410_paramset array
208 * by nid of paramset
926c41bd
DSH
209 *
210 */
0f113f3e
MC
211int fill_GOST94_params(DSA *dsa, int nid)
212{
213 R3410_params *params = R3410_paramset;
214 while (params->nid != NID_undef && params->nid != nid)
215 params++;
216 if (params->nid == NID_undef) {
217 GOSTerr(GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET);
218 return 0;
219 }
a04549cc 220#define dump_signature(a,b,c)
0f113f3e
MC
221 if (dsa->p) {
222 BN_free(dsa->p);
223 }
224 dsa->p = NULL;
225 BN_dec2bn(&(dsa->p), params->p);
226 if (dsa->q) {
227 BN_free(dsa->q);
228 }
229 dsa->q = NULL;
230 BN_dec2bn(&(dsa->q), params->q);
231 if (dsa->g) {
232 BN_free(dsa->g);
233 }
234 dsa->g = NULL;
235 BN_dec2bn(&(dsa->g), params->a);
236 return 1;
237}
a04549cc
DSH
238
239/*
240 * Generate GOST R 34.10-94 keypair
a04549cc 241 *
926c41bd
DSH
242 *
243 */
244int gost_sign_keygen(DSA *dsa)
0f113f3e
MC
245{
246 dsa->priv_key = BN_new();
247 BN_rand_range(dsa->priv_key, dsa->q);
248 return gost94_compute_public(dsa);
249}
926c41bd 250
a04549cc 251/* Unpack signature according to cryptocom rules */
1d97c843 252/*-
926c41bd 253DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen)
0f113f3e
MC
254 {
255 DSA_SIG *s;
256 s = DSA_SIG_new();
257 if (s == NULL)
258 {
259 GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,ERR_R_MALLOC_FAILURE);
260 return(NULL);
261 }
262 s->r = getbnfrombuf(sig, siglen/2);
263 s->s = getbnfrombuf(sig + siglen/2, siglen/2);
264 return s;
265 }
10f0c85c 266*/
a04549cc 267/* Unpack signature according to cryptopro rules */
0f113f3e
MC
268DSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen)
269{
270 DSA_SIG *s;
a04549cc 271
0f113f3e
MC
272 s = DSA_SIG_new();
273 if (s == NULL) {
274 GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE);
275 return NULL;
276 }
277 s->s = getbnfrombuf(sig, siglen / 2);
278 s->r = getbnfrombuf(sig + siglen / 2, siglen / 2);
279 return s;
280}
926c41bd 281
a04549cc 282/* Convert little-endian byte array into bignum */
926c41bd 283BIGNUM *hashsum2bn(const unsigned char *dgst)
0f113f3e
MC
284{
285 unsigned char buf[32];
286 int i;
287 for (i = 0; i < 32; i++) {
288 buf[31 - i] = dgst[i];
289 }
290 return getbnfrombuf(buf, 32);
291}
a04549cc
DSH
292
293/* Convert byte buffer to bignum, skipping leading zeros*/
0f113f3e
MC
294BIGNUM *getbnfrombuf(const unsigned char *buf, size_t len)
295{
296 while (*buf == 0 && len > 0) {
297 buf++;
298 len--;
299 }
300 if (len) {
301 return BN_bin2bn(buf, len, NULL);
302 } else {
303 BIGNUM *b = BN_new();
304 BN_zero(b);
305 return b;
306 }
307}
926c41bd 308
0f113f3e
MC
309/*
310 * Pack bignum into byte buffer of given size, filling all leading bytes by
311 * zeros
312 */
313int store_bignum(BIGNUM *bn, unsigned char *buf, int len)
314{
315 int bytes = BN_num_bytes(bn);
316 if (bytes > len)
317 return 0;
318 memset(buf, 0, len);
319 BN_bn2bin(bn, buf + len - bytes);
320 return 1;
321}