Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4304 - (hide 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 maya 4304 /*
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