Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/key.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4304 - (show annotations) (download) (as text)
Mon Feb 14 09:09:07 2011 UTC (13 years, 1 month ago) by maya
Original Path: trunk/ttssh2/ttxssh/key.c
File MIME type: text/x-csrc
File size: 21083 byte(s)
ssh.c から key.c, kex.c を分割
1 /*
2 Copyright (c) 2011, TeraTerm Project
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this list
12 of conditions and the following disclaimer in the documentation and/or other materials
13 provided with the distribution.
14
15 The name of Robert O'Callahan may not be used to endorse or promote products derived from
16 this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "ttxssh.h"
30 #include "key.h"
31
32 #include <openssl/rsa.h>
33 #include <openssl/dsa.h>
34
35 #define INTBLOB_LEN 20
36 #define SIGBLOB_LEN (2*INTBLOB_LEN)
37
38 //////////////////////////////////////////////////////////////////////////////
39 //
40 // Key verify function
41 //
42 //////////////////////////////////////////////////////////////////////////////
43
44 //
45 // DSS
46 //
47
48 int ssh_dss_verify(DSA *key,
49 u_char *signature, u_int signaturelen,
50 u_char *data, u_int datalen)
51 {
52 DSA_SIG *sig;
53 const EVP_MD *evp_md = EVP_sha1();
54 EVP_MD_CTX md;
55 unsigned char digest[EVP_MAX_MD_SIZE], *sigblob;
56 unsigned int len, dlen;
57 int ret;
58 char *ptr;
59
60 OpenSSL_add_all_digests();
61
62 if (key == NULL) {
63 return -2;
64 }
65
66 ptr = signature;
67
68 // step1
69 if (signaturelen == 0x28) {
70 // workaround for SSH-2.0-2.0* and SSH-2.0-2.1* (2006.11.18 maya)
71 ptr -= 4;
72 }
73 else {
74 len = get_uint32_MSBfirst(ptr);
75 ptr += 4;
76 if (strncmp("ssh-dss", ptr, len) != 0) {
77 return -3;
78 }
79 ptr += len;
80 }
81
82 // step2
83 len = get_uint32_MSBfirst(ptr);
84 ptr += 4;
85 sigblob = ptr;
86 ptr += len;
87
88 if (len != SIGBLOB_LEN) {
89 return -4;
90 }
91
92 /* parse signature */
93 if ((sig = DSA_SIG_new()) == NULL)
94 return -5;
95 if ((sig->r = BN_new()) == NULL)
96 return -6;
97 if ((sig->s = BN_new()) == NULL)
98 return -7;
99 BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
100 BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
101
102 /* sha1 the data */
103 EVP_DigestInit(&md, evp_md);
104 EVP_DigestUpdate(&md, data, datalen);
105 EVP_DigestFinal(&md, digest, &dlen);
106
107 ret = DSA_do_verify(digest, dlen, sig, key);
108 memset(digest, 'd', sizeof(digest));
109
110 DSA_SIG_free(sig);
111
112 return ret;
113 }
114
115
116 //
117 // RSA
118 //
119
120 /*
121 * See:
122 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
123 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
124 */
125 /*
126 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
127 * oiw(14) secsig(3) algorithms(2) 26 }
128 */
129 static const u_char id_sha1[] = {
130 0x30, 0x21, /* type Sequence, length 0x21 (33) */
131 0x30, 0x09, /* type Sequence, length 0x09 */
132 0x06, 0x05, /* type OID, length 0x05 */
133 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
134 0x05, 0x00, /* NULL */
135 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
136 };
137 /*
138 * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
139 * rsadsi(113549) digestAlgorithm(2) 5 }
140 */
141 static const u_char id_md5[] = {
142 0x30, 0x20, /* type Sequence, length 0x20 (32) */
143 0x30, 0x0c, /* type Sequence, length 0x09 */
144 0x06, 0x08, /* type OID, length 0x05 */
145 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */
146 0x05, 0x00, /* NULL */
147 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */
148 };
149
150 static int openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
151 u_char *sigbuf, u_int siglen, RSA *rsa)
152 {
153 u_int ret, rsasize, oidlen = 0, hlen = 0;
154 int len;
155 const u_char *oid = NULL;
156 u_char *decrypted = NULL;
157
158 ret = 0;
159 switch (type) {
160 case NID_sha1:
161 oid = id_sha1;
162 oidlen = sizeof(id_sha1);
163 hlen = 20;
164 break;
165 case NID_md5:
166 oid = id_md5;
167 oidlen = sizeof(id_md5);
168 hlen = 16;
169 break;
170 default:
171 goto done;
172 break;
173 }
174 if (hashlen != hlen) {
175 //error("bad hashlen");
176 goto done;
177 }
178 rsasize = RSA_size(rsa);
179 if (siglen == 0 || siglen > rsasize) {
180 //error("bad siglen");
181 goto done;
182 }
183 decrypted = malloc(rsasize);
184 if (decrypted == NULL)
185 return 1; // error
186
187 if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
188 RSA_PKCS1_PADDING)) < 0) {
189 //error("RSA_public_decrypt failed: %s",
190 // ERR_error_string(ERR_get_error(), NULL));
191 goto done;
192 }
193 if (len != hlen + oidlen) {
194 //error("bad decrypted len: %d != %d + %d", len, hlen, oidlen);
195 goto done;
196 }
197 if (memcmp(decrypted, oid, oidlen) != 0) {
198 //error("oid mismatch");
199 goto done;
200 }
201 if (memcmp(decrypted + oidlen, hash, hlen) != 0) {
202 //error("hash mismatch");
203 goto done;
204 }
205 ret = 1;
206 done:
207 if (decrypted)
208 free(decrypted);
209 return ret;
210 }
211
212 int ssh_rsa_verify(RSA *key,
213 u_char *signature, u_int signaturelen,
214 u_char *data, u_int datalen)
215 {
216 const EVP_MD *evp_md;
217 EVP_MD_CTX md;
218 // char *ktype;
219 u_char digest[EVP_MAX_MD_SIZE], *sigblob;
220 u_int len, dlen, modlen;
221 // int rlen, ret, nid;
222 int ret, nid;
223 char *ptr;
224
225 OpenSSL_add_all_digests();
226
227 if (key == NULL) {
228 return -2;
229 }
230 if (BN_num_bits(key->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
231 return -3;
232 }
233 //debug_print(41, signature, signaturelen);
234 ptr = signature;
235
236 // step1
237 len = get_uint32_MSBfirst(ptr);
238 ptr += 4;
239 if (strncmp("ssh-rsa", ptr, len) != 0) {
240 return -4;
241 }
242 ptr += len;
243
244 // step2
245 len = get_uint32_MSBfirst(ptr);
246 ptr += 4;
247 sigblob = ptr;
248 ptr += len;
249 #if 0
250 rlen = get_uint32_MSBfirst(ptr);
251 if (rlen != 0) {
252 return -1;
253 }
254 #endif
255
256 /* RSA_verify expects a signature of RSA_size */
257 modlen = RSA_size(key);
258 if (len > modlen) {
259 return -5;
260
261 } else if (len < modlen) {
262 u_int diff = modlen - len;
263 sigblob = realloc(sigblob, modlen);
264 memmove(sigblob + diff, sigblob, len);
265 memset(sigblob, 0, diff);
266 len = modlen;
267 }
268
269 /* sha1 the data */
270 // nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
271 nid = NID_sha1;
272 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
273 //error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid);
274 return -6;
275 }
276 EVP_DigestInit(&md, evp_md);
277 EVP_DigestUpdate(&md, data, datalen);
278 EVP_DigestFinal(&md, digest, &dlen);
279
280 ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key);
281
282 memset(digest, 'd', sizeof(digest));
283 memset(sigblob, 's', len);
284 //free(sigblob);
285 //debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : "");
286
287 return ret;
288 }
289
290 int key_verify(RSA *rsa_key, DSA *dsa_key,
291 unsigned char *signature, unsigned int signaturelen,
292 unsigned char *data, unsigned int datalen)
293 {
294 int ret = 0;
295
296 if (rsa_key != NULL) {
297 ret = ssh_rsa_verify(rsa_key, signature, signaturelen, data, datalen);
298
299 } else if (dsa_key != NULL) {
300 ret = ssh_dss_verify(dsa_key, signature, signaturelen, data, datalen);
301
302 } else {
303 return -1;
304 }
305
306 return (ret); // success
307 }
308
309 //
310 // RSA�\����������
311 //
312 RSA *duplicate_RSA(RSA *src)
313 {
314 RSA *rsa = NULL;
315
316 rsa = RSA_new();
317 if (rsa == NULL)
318 goto error;
319 rsa->n = BN_new();
320 rsa->e = BN_new();
321 if (rsa->n == NULL || rsa->e == NULL) {
322 RSA_free(rsa);
323 goto error;
324 }
325
326 // �[���R�s�[(deep copy)���s���B�����R�s�[(shallow copy)��NG�B
327 BN_copy(rsa->n, src->n);
328 BN_copy(rsa->e, src->e);
329
330 error:
331 return (rsa);
332 }
333
334
335 //
336 // DSA�\����������
337 //
338 DSA *duplicate_DSA(DSA *src)
339 {
340 DSA *dsa = NULL;
341
342 dsa = DSA_new();
343 if (dsa == NULL)
344 goto error;
345 dsa->p = BN_new();
346 dsa->q = BN_new();
347 dsa->g = BN_new();
348 dsa->pub_key = BN_new();
349 if (dsa->p == NULL ||
350 dsa->q == NULL ||
351 dsa->g == NULL ||
352 dsa->pub_key == NULL) {
353 DSA_free(dsa);
354 goto error;
355 }
356
357 // �[���R�s�[(deep copy)���s���B�����R�s�[(shallow copy)��NG�B
358 BN_copy(dsa->p, src->p);
359 BN_copy(dsa->q, src->q);
360 BN_copy(dsa->g, src->g);
361 BN_copy(dsa->pub_key, src->pub_key);
362
363 error:
364 return (dsa);
365 }
366
367
368 char* key_fingerprint_raw(Key *k, int *dgst_raw_length)
369 {
370 const EVP_MD *md = NULL;
371 EVP_MD_CTX ctx;
372 char *blob = NULL;
373 char *retval = NULL;
374 int len = 0;
375 int nlen, elen;
376 RSA *rsa;
377
378 *dgst_raw_length = 0;
379
380 // MD5�A���S���Y�����g�p����
381 md = EVP_md5();
382
383 switch (k->type) {
384 case KEY_RSA1:
385 rsa = make_key(NULL, k->bits, k->exp, k->mod);
386 nlen = BN_num_bytes(rsa->n);
387 elen = BN_num_bytes(rsa->e);
388 len = nlen + elen;
389 blob = malloc(len);
390 if (blob == NULL) {
391 // TODO:
392 }
393 BN_bn2bin(rsa->n, blob);
394 BN_bn2bin(rsa->e, blob + nlen);
395 RSA_free(rsa);
396 break;
397
398 case KEY_DSA:
399 case KEY_RSA:
400 key_to_blob(k, &blob, &len);
401 break;
402
403 case KEY_UNSPEC:
404 return retval;
405 break;
406
407 default:
408 //fatal("key_fingerprint_raw: bad key type %d", k->type);
409 break;
410 }
411
412 if (blob != NULL) {
413 retval = malloc(EVP_MAX_MD_SIZE);
414 if (retval == NULL) {
415 // TODO:
416 }
417 EVP_DigestInit(&ctx, md);
418 EVP_DigestUpdate(&ctx, blob, len);
419 EVP_DigestFinal(&ctx, retval, dgst_raw_length);
420 memset(blob, 0, len);
421 free(blob);
422 } else {
423 //fatal("key_fingerprint_raw: blob is null");
424 }
425 return retval;
426 }
427
428
429 const char *
430 key_type(const Key *k)
431 {
432 switch (k->type) {
433 case KEY_RSA1:
434 return "RSA1";
435 case KEY_RSA:
436 return "RSA";
437 case KEY_DSA:
438 return "DSA";
439 }
440 return "unknown";
441 }
442
443 unsigned int
444 key_size(const Key *k)
445 {
446 switch (k->type) {
447 case KEY_RSA1:
448 // SSH1�������� key->rsa �� key->dsa �� NULL �����������A�g�������B
449 return k->bits;
450 case KEY_RSA:
451 return BN_num_bits(k->rsa->n);
452 case KEY_DSA:
453 return BN_num_bits(k->dsa->p);
454 }
455 return 0;
456 }
457
458 // based on OpenSSH 5.1
459 #define FLDBASE 8
460 #define FLDSIZE_Y (FLDBASE + 1)
461 #define FLDSIZE_X (FLDBASE * 2 + 1)
462 static char *
463 key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
464 {
465 /*
466 * Chars to be used after each other every time the worm
467 * intersects with itself. Matter of taste.
468 */
469 char *augmentation_string = " .o+=*BOX@%&#/^SE";
470 char *retval, *p;
471 unsigned char field[FLDSIZE_X][FLDSIZE_Y];
472 unsigned int i, b;
473 int x, y;
474 size_t len = strlen(augmentation_string) - 1;
475
476 retval = calloc(1, (FLDSIZE_X + 3 + 1) * (FLDSIZE_Y + 2));
477
478 /* initialize field */
479 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
480 x = FLDSIZE_X / 2;
481 y = FLDSIZE_Y / 2;
482
483 /* process raw key */
484 for (i = 0; i < dgst_raw_len; i++) {
485 int input;
486 /* each byte conveys four 2-bit move commands */
487 input = dgst_raw[i];
488 for (b = 0; b < 4; b++) {
489 /* evaluate 2 bit, rest is shifted later */
490 x += (input & 0x1) ? 1 : -1;
491 y += (input & 0x2) ? 1 : -1;
492
493 /* assure we are still in bounds */
494 x = max(x, 0);
495 y = max(y, 0);
496 x = min(x, FLDSIZE_X - 1);
497 y = min(y, FLDSIZE_Y - 1);
498
499 /* augment the field */
500 field[x][y]++;
501 input = input >> 2;
502 }
503 }
504
505 /* mark starting point and end point*/
506 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
507 field[x][y] = len;
508
509 /* fill in retval */
510 _snprintf_s(retval, FLDSIZE_X, _TRUNCATE, "+--[%4s %4u]", key_type(k), key_size(k));
511 p = strchr(retval, '\0');
512
513 /* output upper border */
514 for (i = p - retval - 1; i < FLDSIZE_X; i++)
515 *p++ = '-';
516 *p++ = '+';
517 *p++ = '\r';
518 *p++ = '\n';
519
520 /* output content */
521 for (y = 0; y < FLDSIZE_Y; y++) {
522 *p++ = '|';
523 for (x = 0; x < FLDSIZE_X; x++)
524 *p++ = augmentation_string[min(field[x][y], len)];
525 *p++ = '|';
526 *p++ = '\r';
527 *p++ = '\n';
528 }
529
530 /* output lower border */
531 *p++ = '+';
532 for (i = 0; i < FLDSIZE_X; i++)
533 *p++ = '-';
534 *p++ = '+';
535
536 return retval;
537 }
538 #undef FLDBASE
539 #undef FLDSIZE_Y
540 #undef FLDSIZE_X
541
542 //
543 // fingerprint�i�w���F�z�X�g���J�����n�b�V���j����������
544 //
545 char *key_fingerprint(Key *key, enum fp_rep dgst_rep)
546 {
547 char *retval = NULL;
548 unsigned char *dgst_raw;
549 int dgst_raw_len;
550 int i, retval_len;
551
552 // fingerprint���n�b�V���l�i�o�C�i���j��������
553 dgst_raw = key_fingerprint_raw(key, &dgst_raw_len);
554
555 if (dgst_rep == SSH_FP_HEX) {
556 // 16�i�\�L����������
557 retval_len = dgst_raw_len * 3 + 1;
558 retval = malloc(retval_len);
559 retval[0] = '\0';
560 for (i = 0; i < dgst_raw_len; i++) {
561 char hex[4];
562 _snprintf_s(hex, sizeof(hex), _TRUNCATE, "%02x:", dgst_raw[i]);
563 strncat_s(retval, retval_len, hex, _TRUNCATE);
564 }
565
566 /* Remove the trailing ':' character */
567 retval[(dgst_raw_len * 3) - 1] = '\0';
568
569 } else if (dgst_rep == SSH_FP_RANDOMART) {
570 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, key);
571
572 } else {
573
574 }
575
576 memset(dgst_raw, 0, dgst_raw_len);
577 free(dgst_raw);
578
579 return (retval);
580 }
581
582
583 //
584 // �L�[����������������
585 //
586 void key_free(Key *key)
587 {
588 switch (key->type) {
589 case KEY_RSA1:
590 case KEY_RSA:
591 if (key->rsa != NULL)
592 RSA_free(key->rsa);
593 key->rsa = NULL;
594 break;
595
596 case KEY_DSA:
597 if (key->dsa != NULL)
598 DSA_free(key->dsa);
599 key->dsa = NULL;
600 break;
601 }
602 free(key);
603 }
604
605 //
606 // �L�[���������������p����
607 //
608 char *get_sshname_from_key(Key *key)
609 {
610 if (key->type == KEY_RSA) {
611 return "ssh-rsa";
612 } else if (key->type == KEY_DSA) {
613 return "ssh-dss";
614 } else {
615 return "ssh-unknown";
616 }
617 }
618
619
620 //
621 // �L�[������������������������
622 //
623 enum hostkey_type get_keytype_from_name(char *name)
624 {
625 if (strcmp(name, "rsa1") == 0) {
626 return KEY_RSA1;
627 } else if (strcmp(name, "rsa") == 0) {
628 return KEY_RSA;
629 } else if (strcmp(name, "dsa") == 0) {
630 return KEY_DSA;
631 } else if (strcmp(name, "ssh-rsa") == 0) {
632 return KEY_RSA;
633 } else if (strcmp(name, "ssh-dss") == 0) {
634 return KEY_DSA;
635 }
636 return KEY_UNSPEC;
637 }
638
639
640 //
641 // �L�[���������o�b�t�@���������� (for SSH2)
642 // NOTE:
643 //
644 int key_to_blob(Key *key, char **blobp, int *lenp)
645 {
646 buffer_t *b;
647 char *sshname;
648 int len;
649 int ret = 1; // success
650
651 b = buffer_init();
652 sshname = get_sshname_from_key(key);
653
654 if (key->type == KEY_RSA) {
655 buffer_put_string(b, sshname, strlen(sshname));
656 buffer_put_bignum2(b, key->rsa->e);
657 buffer_put_bignum2(b, key->rsa->n);
658
659 } else if (key->type == KEY_DSA) {
660 buffer_put_string(b, sshname, strlen(sshname));
661 buffer_put_bignum2(b, key->dsa->p);
662 buffer_put_bignum2(b, key->dsa->q);
663 buffer_put_bignum2(b, key->dsa->g);
664 buffer_put_bignum2(b, key->dsa->pub_key);
665
666 } else {
667 ret = 0;
668 goto error;
669
670 }
671
672 len = buffer_len(b);
673 if (lenp != NULL)
674 *lenp = len;
675 if (blobp != NULL) {
676 *blobp = malloc(len);
677 if (*blobp == NULL) {
678 ret = 0;
679 goto error;
680 }
681 memcpy(*blobp, buffer_ptr(b), len);
682 }
683
684 error:
685 buffer_free(b);
686
687 return (ret);
688 }
689
690
691 //
692 // �o�b�t�@�����L�[�����������o��(for SSH2)
693 // NOTE: ���l���A���P�[�g���������������A�����o�������������������B
694 //
695 Key *key_from_blob(char *data, int blen)
696 {
697 int keynamelen;
698 char key[128];
699 RSA *rsa = NULL;
700 DSA *dsa = NULL;
701 Key *hostkey; // hostkey
702 enum hostkey_type type;
703
704 hostkey = malloc(sizeof(Key));
705 if (hostkey == NULL)
706 goto error;
707
708 memset(hostkey, 0, sizeof(Key));
709
710 keynamelen = get_uint32_MSBfirst(data);
711 if (keynamelen >= sizeof(key)) {
712 goto error;
713 }
714 data += 4;
715 memcpy(key, data, keynamelen);
716 key[keynamelen] = 0;
717 data += keynamelen;
718
719 type = get_keytype_from_name(key);
720
721 // RSA key
722 if (type == KEY_RSA) {
723 rsa = RSA_new();
724 if (rsa == NULL) {
725 goto error;
726 }
727 rsa->n = BN_new();
728 rsa->e = BN_new();
729 if (rsa->n == NULL || rsa->e == NULL) {
730 goto error;
731 }
732
733 buffer_get_bignum2(&data, rsa->e);
734 buffer_get_bignum2(&data, rsa->n);
735
736 hostkey->type = type;
737 hostkey->rsa = rsa;
738
739 } else if (type == KEY_DSA) { // DSA key
740 dsa = DSA_new();
741 if (dsa == NULL) {
742 goto error;
743 }
744 dsa->p = BN_new();
745 dsa->q = BN_new();
746 dsa->g = BN_new();
747 dsa->pub_key = BN_new();
748 if (dsa->p == NULL ||
749 dsa->q == NULL ||
750 dsa->g == NULL ||
751 dsa->pub_key == NULL) {
752 goto error;
753 }
754
755 buffer_get_bignum2(&data, dsa->p);
756 buffer_get_bignum2(&data, dsa->q);
757 buffer_get_bignum2(&data, dsa->g);
758 buffer_get_bignum2(&data, dsa->pub_key);
759
760 hostkey->type = type;
761 hostkey->dsa = dsa;
762
763 } else {
764 // unknown key
765 goto error;
766
767 }
768
769 return (hostkey);
770
771 error:
772 if (rsa != NULL)
773 RSA_free(rsa);
774 if (dsa != NULL)
775 DSA_free(dsa);
776
777 return NULL;
778 }
779
780 char *get_SSH2_keyname(CRYPTKeyPair *keypair)
781 {
782 char *s;
783
784 if (keypair->RSA_key != NULL) {
785 s = "ssh-rsa";
786 } else {
787 s = "ssh-dss";
788 }
789
790 return (s);
791 }
792
793
794 BOOL generate_SSH2_keysign(CRYPTKeyPair *keypair, char **sigptr, int *siglen, char *data, int datalen)
795 {
796 buffer_t *msg = NULL;
797 char *s;
798
799 msg = buffer_init();
800 if (msg == NULL) {
801 // TODO: error check
802 return FALSE;
803 }
804
805 if (keypair->RSA_key != NULL) { // RSA
806 const EVP_MD *evp_md;
807 EVP_MD_CTX md;
808 u_char digest[EVP_MAX_MD_SIZE], *sig;
809 u_int slen, dlen, len;
810 int ok, nid;
811
812 nid = NID_sha1;
813 if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
814 goto error;
815 }
816
817 // �_�C�W�F�X�g�l���v�Z
818 EVP_DigestInit(&md, evp_md);
819 EVP_DigestUpdate(&md, data, datalen);
820 EVP_DigestFinal(&md, digest, &dlen);
821
822 slen = RSA_size(keypair->RSA_key);
823 sig = malloc(slen);
824 if (sig == NULL)
825 goto error;
826
827 // �d�q�������v�Z
828 ok = RSA_sign(nid, digest, dlen, sig, &len, keypair->RSA_key);
829 memset(digest, 'd', sizeof(digest));
830 if (ok != 1) { // error
831 free(sig);
832 goto error;
833 }
834 // �������T�C�Y���o�b�t�@���������������A�������������B�������[�����������B
835 if (len < slen) {
836 u_int diff = slen - len;
837 memmove(sig + diff, sig, len);
838 memset(sig, 0, diff);
839
840 } else if (len > slen) {
841 free(sig);
842 goto error;
843
844 } else {
845 // do nothing
846
847 }
848
849 s = get_SSH2_keyname(keypair);
850 buffer_put_string(msg, s, strlen(s));
851 buffer_append_length(msg, sig, slen);
852 len = buffer_len(msg);
853
854 // setting
855 *siglen = len;
856 *sigptr = malloc(len);
857 if (*sigptr == NULL) {
858 free(sig);
859 goto error;
860 }
861 memcpy(*sigptr, buffer_ptr(msg), len);
862 free(sig);
863
864 } else { // DSA
865 DSA_SIG *sig;
866 const EVP_MD *evp_md = EVP_sha1();
867 EVP_MD_CTX md;
868 u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
869 u_int rlen, slen, len, dlen;
870
871 // �_�C�W�F�X�g���v�Z
872 EVP_DigestInit(&md, evp_md);
873 EVP_DigestUpdate(&md, data, datalen);
874 EVP_DigestFinal(&md, digest, &dlen);
875
876 // DSA�d�q�������v�Z
877 sig = DSA_do_sign(digest, dlen, keypair->DSA_key);
878 memset(digest, 'd', sizeof(digest));
879 if (sig == NULL) {
880 goto error;
881 }
882
883 // BIGNUM�����o�C�i���l��������
884 rlen = BN_num_bytes(sig->r);
885 slen = BN_num_bytes(sig->s);
886 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
887 DSA_SIG_free(sig);
888 goto error;
889 }
890 memset(sigblob, 0, SIGBLOB_LEN);
891 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
892 BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
893 DSA_SIG_free(sig);
894
895 // setting
896 s = get_SSH2_keyname(keypair);
897 buffer_put_string(msg, s, strlen(s));
898 buffer_append_length(msg, sigblob, sizeof(sigblob));
899 len = buffer_len(msg);
900
901 // setting
902 *siglen = len;
903 *sigptr = malloc(len);
904 if (*sigptr == NULL) {
905 goto error;
906 }
907 memcpy(*sigptr, buffer_ptr(msg), len);
908
909 }
910
911 buffer_free(msg);
912 return TRUE;
913
914 error:
915 buffer_free(msg);
916
917 return FALSE;
918 }
919
920
921 BOOL get_SSH2_publickey_blob(PTInstVar pvar, buffer_t **blobptr, int *bloblen)
922 {
923 buffer_t *msg = NULL;
924 CRYPTKeyPair *keypair;
925 char *s;
926
927 msg = buffer_init();
928 if (msg == NULL) {
929 // TODO: error check
930 return FALSE;
931 }
932
933 keypair = pvar->auth_state.cur_cred.key_pair;
934
935 if (keypair->RSA_key != NULL) { // RSA
936 s = get_SSH2_keyname(keypair);
937 buffer_put_string(msg, s, strlen(s));
938 buffer_put_bignum2(msg, keypair->RSA_key->e); // ���J�w��
939 buffer_put_bignum2(msg, keypair->RSA_key->n); // p�~q
940
941 } else { // DSA
942 s = get_SSH2_keyname(keypair);
943 buffer_put_string(msg, s, strlen(s));
944 buffer_put_bignum2(msg, keypair->DSA_key->p); // �f��
945 buffer_put_bignum2(msg, keypair->DSA_key->q); // (p-1)���f����
946 buffer_put_bignum2(msg, keypair->DSA_key->g); // ����
947 buffer_put_bignum2(msg, keypair->DSA_key->pub_key); // ���J��
948
949 }
950
951 *blobptr = msg;
952 *bloblen = buffer_len(msg);
953
954 return TRUE;
955 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26