* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Encrypt.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Encrypt.c\r
79 // 暗号化および電子証明書ルーチン\r
80 \r
81 #define ENCRYPT_C\r
82 \r
83 #define __WINCRYPT_H__\r
84 \r
85 #include <stdio.h>\r
86 #include <stdlib.h>\r
87 #include <string.h>\r
88 #include <wchar.h>\r
89 #include <stdarg.h>\r
90 #include <time.h>\r
91 #include <errno.h>\r
92 #include <openssl/ssl.h>\r
93 #include <openssl/err.h>\r
94 #include <openssl/rand.h>\r
95 #include <openssl/engine.h>\r
96 #include <openssl/bio.h>\r
97 #include <openssl/x509.h>\r
98 #include <openssl/pkcs7.h>\r
99 #include <openssl/pkcs12.h>\r
100 #include <openssl/rc4.h>\r
101 #include <openssl/md5.h>\r
102 #include <openssl/sha.h>\r
103 #include <Mayaqua/Mayaqua.h>\r
104 \r
105 LOCK *openssl_lock = NULL;\r
106 \r
107 LOCK **ssl_lock_obj = NULL;\r
108 UINT ssl_lock_num;\r
109 static bool openssl_inited = false;\r
110 \r
111 // コールバック関数用\r
112 typedef struct CB_PARAM\r
113 {\r
114         char *password;\r
115 } CB_PARAM;\r
116 \r
117 // 証明書が特定のディレクトリの CRL によって無効化されているかどうか確認する\r
118 bool IsXRevoked(X *x)\r
119 {\r
120         char dirname[MAX_PATH];\r
121         UINT i;\r
122         bool ret = false;\r
123         DIRLIST *t;\r
124         // 引数チェック\r
125         if (x == NULL)\r
126         {\r
127                 return false;\r
128         }\r
129 \r
130         GetExeDir(dirname, sizeof(dirname));\r
131 \r
132         // CRL ファイルの検索\r
133         t = EnumDir(dirname);\r
134 \r
135         for (i = 0;i < t->NumFiles;i++)\r
136         {\r
137                 char *name = t->File[i]->FileName;\r
138                 if (t->File[i]->Folder == false)\r
139                 {\r
140                         if (EndWith(name, ".crl"))\r
141                         {\r
142                                 char filename[MAX_PATH];\r
143                                 X_CRL *r;\r
144 \r
145                                 ConbinePath(filename, sizeof(filename), dirname, name);\r
146 \r
147                                 r = FileToXCrl(filename);\r
148 \r
149                                 if (r != NULL)\r
150                                 {\r
151                                         if (IsXRevokedByXCrl(x, r))\r
152                                         {\r
153                                                 ret = true;\r
154                                         }\r
155 \r
156                                         FreeXCrl(r);\r
157                                 }\r
158                         }\r
159                 }\r
160         }\r
161 \r
162         FreeDir(t);\r
163 \r
164         return ret;\r
165 }\r
166 \r
167 // 証明書が CRL によって無効化されているかどうか確認する\r
168 bool IsXRevokedByXCrl(X *x, X_CRL *r)\r
169 {\r
170 #ifdef  OS_WIN32\r
171         X509_REVOKED tmp;\r
172         X509_CRL_INFO *info;\r
173         int index;\r
174         // 引数チェック\r
175         if (x == NULL || r == NULL)\r
176         {\r
177                 return false;\r
178         }\r
179 \r
180         Zero(&tmp, sizeof(tmp));\r
181         tmp.serialNumber = X509_get_serialNumber(x->x509);\r
182 \r
183         info = r->Crl->crl;\r
184 \r
185         if (sk_X509_REVOKED_is_sorted(info->revoked) == false)\r
186         {\r
187                 sk_X509_REVOKED_sort(info->revoked);\r
188         }\r
189 \r
190         index = sk_X509_REVOKED_find(info->revoked, &tmp);\r
191 \r
192         if (index < 0)\r
193         {\r
194                 return false;\r
195         }\r
196         else\r
197         {\r
198                 return true;\r
199         }\r
200 #else   // OS_WIN32\r
201         return false;\r
202 #endif  // OS_WIN32\r
203 }\r
204 \r
205 // CRL の解放\r
206 void FreeXCrl(X_CRL *r)\r
207 {\r
208         // 引数チェック\r
209         if (r == NULL)\r
210         {\r
211                 return;\r
212         }\r
213 \r
214         X509_CRL_free(r->Crl);\r
215 \r
216         Free(r);\r
217 }\r
218 \r
219 // ファイルを CRL に変換\r
220 X_CRL *FileToXCrl(char *filename)\r
221 {\r
222         wchar_t *filename_w = CopyStrToUni(filename);\r
223         X_CRL *ret = FileToXCrlW(filename_w);\r
224 \r
225         Free(filename_w);\r
226 \r
227         return ret;\r
228 }\r
229 X_CRL *FileToXCrlW(wchar_t *filename)\r
230 {\r
231         BUF *b;\r
232         X_CRL *r;\r
233         // 引数チェック\r
234         if (filename == NULL)\r
235         {\r
236                 return NULL;\r
237         }\r
238 \r
239         b = ReadDumpW(filename);\r
240         if (b == NULL)\r
241         {\r
242                 return NULL;\r
243         }\r
244 \r
245         r = BufToXCrl(b);\r
246 \r
247         FreeBuf(b);\r
248 \r
249         return r;\r
250 }\r
251 \r
252 // バッファを CRL に変換\r
253 X_CRL *BufToXCrl(BUF *b)\r
254 {\r
255         X_CRL *r;\r
256         X509_CRL *x509crl;\r
257         BIO *bio;\r
258         // 引数チェック\r
259         if (b == NULL)\r
260         {\r
261                 return NULL;\r
262         }\r
263 \r
264         bio = BufToBio(b);\r
265         if (bio == NULL)\r
266         {\r
267                 return NULL;\r
268         }\r
269 \r
270         x509crl = NULL;\r
271 \r
272         if (d2i_X509_CRL_bio(bio, &x509crl) == NULL || x509crl == NULL)\r
273         {\r
274                 FreeBio(bio);\r
275                 return NULL;\r
276         }\r
277 \r
278         r = ZeroMalloc(sizeof(X_CRL));\r
279         r->Crl = x509crl;\r
280 \r
281         FreeBio(bio);\r
282 \r
283         return r;\r
284 }\r
285 \r
286 // バッファを公開鍵に変換\r
287 K *RsaBinToPublic(void *data, UINT size)\r
288 {\r
289         RSA *rsa;\r
290         K *k;\r
291         BIO *bio;\r
292         // 引数チェック\r
293         if (data == NULL || size < 4)\r
294         {\r
295                 return NULL;\r
296         }\r
297 \r
298         rsa = RSA_new();\r
299 \r
300         if (rsa->e != NULL)\r
301         {\r
302                 BN_free(rsa->e);\r
303         }\r
304 \r
305         rsa->e = BN_new();\r
306         BN_set_word(rsa->e, RSA_F4);\r
307 \r
308         if (rsa->n != NULL)\r
309         {\r
310                 BN_free(rsa->n);\r
311         }\r
312 \r
313         rsa->n = BinToBigNum(data, size);\r
314 \r
315         bio = NewBio();\r
316         Lock(openssl_lock);\r
317         {\r
318                 i2d_RSA_PUBKEY_bio(bio, rsa);\r
319         }\r
320         Unlock(openssl_lock);\r
321         BIO_seek(bio, 0);\r
322         k = BioToK(bio, false, false, NULL);\r
323         FreeBio(bio);\r
324 \r
325         RSA_free(rsa);\r
326 \r
327         return k;\r
328 }\r
329 \r
330 // 公開鍵をバッファに変換\r
331 BUF *RsaPublicToBuf(K *k)\r
332 {\r
333         BUF *b;\r
334         // 引数チェック\r
335         if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL\r
336                 || k->pkey->pkey.rsa->n == NULL)\r
337         {\r
338                 return NULL;\r
339         }\r
340 \r
341         b = BigNumToBuf(k->pkey->pkey.rsa->n);\r
342         if (b == NULL)\r
343         {\r
344                 return NULL;\r
345         }\r
346 \r
347         return b;\r
348 }\r
349 \r
350 // 公開鍵をバイナリに変換\r
351 void RsaPublicToBin(K *k, void *data)\r
352 {\r
353         BUF *b;\r
354         // 引数チェック\r
355         if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL\r
356                 || k->pkey->pkey.rsa->n == NULL || data == NULL)\r
357         {\r
358                 return;\r
359         }\r
360 \r
361         b = BigNumToBuf(k->pkey->pkey.rsa->n);\r
362         if (b == NULL)\r
363         {\r
364                 return;\r
365         }\r
366 \r
367         Copy(data, b->Buf, b->Size);\r
368 \r
369         FreeBuf(b);\r
370 }\r
371 \r
372 // 公開鍵サイズの取得\r
373 UINT RsaPublicSize(K *k)\r
374 {\r
375         BUF *b;\r
376         UINT ret;\r
377         // 引数チェック\r
378         if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL\r
379                 || k->pkey->pkey.rsa->n == NULL)\r
380         {\r
381                 return 0;\r
382         }\r
383 \r
384         b = BigNumToBuf(k->pkey->pkey.rsa->n);\r
385         if (b == NULL)\r
386         {\r
387                 return 0;\r
388         }\r
389 \r
390         ret = b->Size;\r
391 \r
392         FreeBuf(b);\r
393 \r
394         return ret;\r
395 }\r
396 \r
397 // ポインタを 32 ビットにハッシュする\r
398 UINT HashPtrToUINT(void *p)\r
399 {\r
400         UCHAR hash_data[MD5_SIZE];\r
401         UINT ret;\r
402         // 引数チェック\r
403         if (p == NULL)\r
404         {\r
405                 return 0;\r
406         }\r
407 \r
408         Hash(hash_data, &p, sizeof(p), false);\r
409 \r
410         Copy(&ret, hash_data, sizeof(ret));\r
411 \r
412         return ret;\r
413 }\r
414 \r
415 // NAME のコピー\r
416 NAME *CopyName(NAME *n)\r
417 {\r
418         // 引数チェック\r
419         if (n == NULL)\r
420         {\r
421                 return NULL;\r
422         }\r
423 \r
424         return NewName(n->CommonName, n->Organization, n->Unit,\r
425                 n->Country, n->State, n->Local);\r
426 }\r
427 \r
428 // バイナリを BIGNUM に変換\r
429 BIGNUM *BinToBigNum(void *data, UINT size)\r
430 {\r
431         BIGNUM *bn;\r
432         // 引数チェック\r
433         if (data == NULL)\r
434         {\r
435                 return NULL;\r
436         }\r
437 \r
438         bn = BN_new();\r
439         BN_bin2bn(data, size, bn);\r
440 \r
441         return bn;\r
442 }\r
443 \r
444 // バッファを BIGNUM に変換\r
445 BIGNUM *BufToBigNum(BUF *b)\r
446 {\r
447         if (b == NULL)\r
448         {\r
449                 return NULL;\r
450         }\r
451 \r
452         return BinToBigNum(b->Buf, b->Size);\r
453 }\r
454 \r
455 // BIGNUM をバッファに変換\r
456 BUF *BigNumToBuf(BIGNUM *bn)\r
457 {\r
458         UINT size;\r
459         UCHAR *tmp;\r
460         BUF *b;\r
461         // 引数チェック\r
462         if (bn == NULL)\r
463         {\r
464                 return NULL;\r
465         }\r
466 \r
467         size = BN_num_bytes(bn);\r
468         tmp = ZeroMalloc(size);\r
469         BN_bn2bin(bn, tmp);\r
470 \r
471         b = NewBuf();\r
472         WriteBuf(b, tmp, size);\r
473         Free(tmp);\r
474 \r
475         SeekBuf(b, 0, 0);\r
476 \r
477         return b;\r
478 }\r
479 \r
480 // OpenSSL のロックの初期化\r
481 void OpenSSL_InitLock()\r
482 {\r
483         UINT i;\r
484 \r
485         // ロックオブジェクトの初期化\r
486         ssl_lock_num = CRYPTO_num_locks();\r
487         ssl_lock_obj = Malloc(sizeof(LOCK *) * ssl_lock_num);\r
488         for (i = 0;i < ssl_lock_num;i++)\r
489         {\r
490                 ssl_lock_obj[i] = NewLock();\r
491         }\r
492 \r
493         // ロック関数の設定\r
494         CRYPTO_set_locking_callback(OpenSSL_Lock);\r
495         CRYPTO_set_id_callback(OpenSSL_Id);\r
496 }\r
497 \r
498 // OpenSSL のロックの解放\r
499 void OpenSSL_FreeLock()\r
500 {\r
501         UINT i;\r
502 \r
503         for (i = 0;i < ssl_lock_num;i++)\r
504         {\r
505                 DeleteLock(ssl_lock_obj[i]);\r
506         }\r
507         Free(ssl_lock_obj);\r
508         ssl_lock_obj = NULL;\r
509 \r
510         CRYPTO_set_locking_callback(NULL);\r
511         CRYPTO_set_id_callback(NULL);\r
512 }\r
513 \r
514 // OpenSSL のロック関数\r
515 void OpenSSL_Lock(int mode, int n, const char *file, int line)\r
516 {\r
517         LOCK *lock = ssl_lock_obj[n];\r
518 \r
519         if (mode & CRYPTO_LOCK)\r
520         {\r
521                 // ロック\r
522                 Lock(lock);\r
523         }\r
524         else\r
525         {\r
526                 // ロック解除\r
527                 Unlock(lock);\r
528         }\r
529 }\r
530 \r
531 // スレッド ID の返却\r
532 unsigned long OpenSSL_Id(void)\r
533 {\r
534         return (unsigned long)ThreadId();\r
535 }\r
536 \r
537 // 証明書の表示名を取得\r
538 void GetPrintNameFromX(wchar_t *str, UINT size, X *x)\r
539 {\r
540         // 引数チェック\r
541         if (x == NULL || str == NULL)\r
542         {\r
543                 return;\r
544         }\r
545 \r
546         GetPrintNameFromName(str, size, x->subject_name);\r
547 }\r
548 void GetPrintNameFromXA(char *str, UINT size, X *x)\r
549 {\r
550         wchar_t tmp[MAX_SIZE];\r
551         // 引数チェック\r
552         if (str == NULL || x == NULL)\r
553         {\r
554                 return;\r
555         }\r
556 \r
557         GetPrintNameFromX(tmp, sizeof(tmp), x);\r
558 \r
559         UniToStr(str, size, tmp);\r
560 }\r
561 void GetAllNameFromXEx(wchar_t *str, UINT size, X *x)\r
562 {\r
563         // 引数チェック\r
564         if (x == NULL || str == NULL)\r
565         {\r
566                 return;\r
567         }\r
568 \r
569         GetAllNameFromNameEx(str, size, x->subject_name);\r
570 }\r
571 void GetAllNameFromXExA(char *str, UINT size, X *x)\r
572 {\r
573         wchar_t tmp[MAX_SIZE];\r
574         // 引数チェック\r
575         if (str == NULL || x == NULL)\r
576         {\r
577                 return;\r
578         }\r
579 \r
580         GetAllNameFromXEx(tmp, sizeof(tmp), x);\r
581 \r
582         UniToStr(str, size, tmp);\r
583 }\r
584 \r
585 // NAME から表示名を取得\r
586 void GetPrintNameFromName(wchar_t *str, UINT size, NAME *name)\r
587 {\r
588         // 引数チェック\r
589         if (str == NULL || name == NULL)\r
590         {\r
591                 return;\r
592         }\r
593 \r
594         if (name->CommonName != NULL)\r
595         {\r
596                 UniStrCpy(str, size, name->CommonName);\r
597         }\r
598         else if (name->Organization != NULL)\r
599         {\r
600                 UniStrCpy(str, size, name->Organization);\r
601         }\r
602         else if (name->Unit != NULL)\r
603         {\r
604                 UniStrCpy(str, size, name->Unit);\r
605         }\r
606         else if (name->State != NULL)\r
607         {\r
608                 UniStrCpy(str, size, name->State);\r
609         }\r
610         else if (name->Local != NULL)\r
611         {\r
612                 UniStrCpy(str, size, name->Local);\r
613         }\r
614         else if (name->Country != NULL)\r
615         {\r
616                 UniStrCpy(str, size, name->Country);\r
617         }\r
618         else\r
619         {\r
620                 UniStrCpy(str, size, L"untitled");\r
621         }\r
622 }\r
623 \r
624 // 証明書からすべての名前文字列を取得\r
625 void GetAllNameFromX(wchar_t *str, UINT size, X *x)\r
626 {\r
627         UCHAR md5[MD5_SIZE], sha1[SHA1_SIZE];\r
628         char tmp1[MD5_SIZE * 3 + 8], tmp2[SHA1_SIZE * 3 + 8];\r
629         wchar_t tmp3[sizeof(tmp1) + sizeof(tmp2) + 64];\r
630         // 引数チェック\r
631         if (str == NULL || x == NULL)\r
632         {\r
633                 return;\r
634         }\r
635 \r
636         GetAllNameFromName(str, size, x->subject_name);\r
637 \r
638         if (x->serial != NULL && x->serial->size >= 1)\r
639         {\r
640                 char tmp[128];\r
641                 wchar_t tmp2[128];\r
642 \r
643                 BinToStr(tmp, sizeof(tmp), x->serial->data, x->serial->size);\r
644                 UniFormat(tmp2, sizeof(tmp2), L", SERIAL=\"%S\"", tmp);\r
645 \r
646                 UniStrCat(str, size, tmp2);\r
647         }\r
648 \r
649         // ダイジェスト値\r
650         GetXDigest(x, md5, false);\r
651         GetXDigest(x, sha1, true);\r
652 \r
653         BinToStr(tmp1, sizeof(tmp1), md5, MD5_SIZE);\r
654         BinToStr(tmp2, sizeof(tmp2), sha1, SHA1_SIZE);\r
655 \r
656         UniFormat(tmp3, sizeof(tmp3), L" (Digest: MD5=\"%S\", SHA1=\"%S\")", tmp1, tmp2);\r
657         UniStrCat(str, size, tmp3);\r
658 }\r
659 void GetAllNameFromA(char *str, UINT size, X *x)\r
660 {\r
661         wchar_t tmp[MAX_SIZE];\r
662         // 引数チェック\r
663         if (str == NULL || x == NULL)\r
664         {\r
665                 return;\r
666         }\r
667 \r
668         GetAllNameFromX(tmp, sizeof(tmp), x);\r
669         UniToStr(str, size, tmp);\r
670 }\r
671 \r
672 // NAME からすべての名前文字列を取得\r
673 void GetAllNameFromName(wchar_t *str, UINT size, NAME *name)\r
674 {\r
675         // 引数チェック\r
676         if (str == NULL || name == NULL)\r
677         {\r
678                 return;\r
679         }\r
680 \r
681         UniStrCpy(str, size, L"");\r
682         if (name->CommonName != NULL)\r
683         {\r
684                 UniFormat(str, size, L"%sCN=%s, ", str, name->CommonName);\r
685         }\r
686         if (name->Organization != NULL)\r
687         {\r
688                 UniFormat(str, size, L"%sO=%s, ", str, name->Organization);\r
689         }\r
690         if (name->Unit != NULL)\r
691         {\r
692                 UniFormat(str, size, L"%sOU=%s, ", str, name->Unit);\r
693         }\r
694         if (name->State != NULL)\r
695         {\r
696                 UniFormat(str, size, L"%sS=%s, ", str, name->State);\r
697         }\r
698         if (name->Local != NULL)\r
699         {\r
700                 UniFormat(str, size, L"%sL=%s, ", str, name->Local);\r
701         }\r
702         if (name->Country != NULL)\r
703         {\r
704                 UniFormat(str, size, L"%sC=%s, ", str, name->Country);\r
705         }\r
706 \r
707         if (UniStrLen(str) >= 3)\r
708         {\r
709                 UINT len = UniStrLen(str);\r
710                 if (str[len - 2] == L',' &&\r
711                         str[len - 1] == L' ')\r
712                 {\r
713                         str[len - 2] = 0;\r
714                 }\r
715         }\r
716 }\r
717 void GetAllNameFromNameEx(wchar_t *str, UINT size, NAME *name)\r
718 {\r
719         // 引数チェック\r
720         if (str == NULL || name == NULL)\r
721         {\r
722                 return;\r
723         }\r
724 \r
725         UniStrCpy(str, size, L"");\r
726         if (name->CommonName != NULL)\r
727         {\r
728                 UniFormat(str, size, L"%s%s, ", str, name->CommonName);\r
729         }\r
730         if (name->Organization != NULL)\r
731         {\r
732                 UniFormat(str, size, L"%s%s, ", str, name->Organization);\r
733         }\r
734         if (name->Unit != NULL)\r
735         {\r
736                 UniFormat(str, size, L"%s%s, ", str, name->Unit);\r
737         }\r
738         if (name->State != NULL)\r
739         {\r
740                 UniFormat(str, size, L"%s%s, ", str, name->State);\r
741         }\r
742         if (name->Local != NULL)\r
743         {\r
744                 UniFormat(str, size, L"%s%s, ", str, name->Local);\r
745         }\r
746         if (name->Country != NULL)\r
747         {\r
748                 UniFormat(str, size, L"%s%s, ", str, name->Country);\r
749         }\r
750 \r
751         if (UniStrLen(str) >= 3)\r
752         {\r
753                 UINT len = UniStrLen(str);\r
754                 if (str[len - 2] == L',' &&\r
755                         str[len - 1] == L' ')\r
756                 {\r
757                         str[len - 2] = 0;\r
758                 }\r
759         }\r
760 }\r
761 \r
762 // 鍵のクローン\r
763 K *CloneK(K *k)\r
764 {\r
765         BUF *b;\r
766         K *ret;\r
767         // 引数チェック\r
768         if (k == NULL)\r
769         {\r
770                 return NULL;\r
771         }\r
772 \r
773         b = KToBuf(k, false, NULL);\r
774         if (b == NULL)\r
775         {\r
776                 return NULL;\r
777         }\r
778 \r
779         ret = BufToK(b, k->private_key, false, NULL);\r
780         FreeBuf(b);\r
781 \r
782         return ret;\r
783 }\r
784 \r
785 // 証明書のクローン\r
786 X *CloneX(X *x)\r
787 {\r
788         BUF *b;\r
789         X *ret;\r
790         // 引数チェック\r
791         if (x == NULL)\r
792         {\r
793                 return NULL;\r
794         }\r
795 \r
796         b = XToBuf(x, false);\r
797         if (b == NULL)\r
798         {\r
799                 return NULL;\r
800         }\r
801 \r
802         ret = BufToX(b, false);\r
803         FreeBuf(b);\r
804 \r
805         return ret;\r
806 }\r
807 \r
808 // P12 を生成する\r
809 P12 *NewP12(X *x, K *k, char *password)\r
810 {\r
811         PKCS12 *pkcs12;\r
812         P12 *p12;\r
813         // 引数チェック\r
814         if (x == NULL || k == NULL)\r
815         {\r
816                 return false;\r
817         }\r
818         if (password && StrLen(password) == 0)\r
819         {\r
820                 password = NULL;\r
821         }\r
822 \r
823         Lock(openssl_lock);\r
824         {\r
825                 pkcs12 = PKCS12_create(password, NULL, k->pkey, x->x509, NULL, 0, 0, 0, 0, 0);\r
826                 if (pkcs12 == NULL)\r
827                 {\r
828                         Unlock(openssl_lock);\r
829                         return NULL;\r
830                 }\r
831         }\r
832         Unlock(openssl_lock);\r
833 \r
834         p12 = PKCS12ToP12(pkcs12);\r
835 \r
836         return p12;\r
837 }\r
838 \r
839 // P12 が暗号化されているかどうかチェックする\r
840 bool IsEncryptedP12(P12 *p12)\r
841 {\r
842         X *x;\r
843         K *k;\r
844         // 引数チェック\r
845         if (p12 == NULL)\r
846         {\r
847                 return false;\r
848         }\r
849 \r
850         if (ParseP12(p12, &x, &k, NULL) == true)\r
851         {\r
852                 FreeX(x);\r
853                 FreeK(k);\r
854                 return false;\r
855         }\r
856 \r
857         return true;\r
858 }\r
859 \r
860 // P12 から X と K を取り出す\r
861 bool ParseP12(P12 *p12, X **x, K **k, char *password)\r
862 {\r
863         EVP_PKEY *pkey;\r
864         X509 *x509;\r
865         // 引数チェック\r
866         if (p12 == NULL || x == NULL || k == NULL)\r
867         {\r
868                 return false;\r
869         }\r
870         if (password && StrLen(password) == 0)\r
871         {\r
872                 password = NULL;\r
873         }\r
874         if (password == NULL)\r
875         {\r
876                 password = "";\r
877         }\r
878 \r
879         // パスワード確認\r
880         Lock(openssl_lock);\r
881         {\r
882                 if (PKCS12_verify_mac(p12->pkcs12, password, -1) == false &&\r
883                         PKCS12_verify_mac(p12->pkcs12, NULL, -1) == false)\r
884                 {\r
885                         Unlock(openssl_lock);\r
886                         return false;\r
887                 }\r
888         }\r
889         Unlock(openssl_lock);\r
890 \r
891         // 抽出\r
892         Lock(openssl_lock);\r
893         {\r
894                 if (PKCS12_parse(p12->pkcs12, password, &pkey, &x509, NULL) == false)\r
895                 {\r
896                         if (PKCS12_parse(p12->pkcs12, NULL, &pkey, &x509, NULL) == false)\r
897                         {\r
898                                 Unlock(openssl_lock);\r
899                                 return false;\r
900                         }\r
901                 }\r
902         }\r
903         Unlock(openssl_lock);\r
904 \r
905         // 変換\r
906         *x = X509ToX(x509);\r
907 \r
908         if (*x == NULL)\r
909         {\r
910                 FreePKey(pkey);\r
911                 return false;\r
912         }\r
913 \r
914         *k = ZeroMalloc(sizeof(K));\r
915         (*k)->private_key = true;\r
916         (*k)->pkey = pkey;\r
917 \r
918         return true;\r
919 }\r
920 \r
921 // P12 をファイルに書き出す\r
922 bool P12ToFile(P12 *p12, char *filename)\r
923 {\r
924         wchar_t *filename_w = CopyStrToUni(filename);\r
925         bool ret = P12ToFileW(p12, filename_w);\r
926 \r
927         return ret;\r
928 }\r
929 bool P12ToFileW(P12 *p12, wchar_t *filename)\r
930 {\r
931         BUF *b;\r
932         // 引数チェック\r
933         if (p12 == NULL || filename == NULL)\r
934         {\r
935                 return false;\r
936         }\r
937 \r
938         b = P12ToBuf(p12);\r
939         if (b == NULL)\r
940         {\r
941                 return false;\r
942         }\r
943 \r
944         if (DumpBufW(b, filename) == false)\r
945         {\r
946                 FreeBuf(b);\r
947                 return false;\r
948         }\r
949 \r
950         FreeBuf(b);\r
951 \r
952         return true;\r
953 }\r
954 \r
955 // ファイルから P12 を読み込む\r
956 P12 *FileToP12(char *filename)\r
957 {\r
958         wchar_t *filename_w = CopyStrToUni(filename);\r
959         P12 *ret = FileToP12W(filename_w);\r
960 \r
961         Free(filename_w);\r
962 \r
963         return ret;\r
964 }\r
965 P12 *FileToP12W(wchar_t *filename)\r
966 {\r
967         BUF *b;\r
968         P12 *p12;\r
969         // 引数チェック\r
970         if (filename == NULL)\r
971         {\r
972                 return NULL;\r
973         }\r
974 \r
975         b = ReadDumpW(filename);\r
976         if (b == NULL)\r
977         {\r
978                 return NULL;\r
979         }\r
980 \r
981         p12 = BufToP12(b);\r
982         FreeBuf(b);\r
983 \r
984         return p12;\r
985 }\r
986 \r
987 // P12 の解放\r
988 void FreeP12(P12 *p12)\r
989 {\r
990         // 引数チェック\r
991         if (p12 == NULL)\r
992         {\r
993                 return;\r
994         }\r
995 \r
996         FreePKCS12(p12->pkcs12);\r
997         Free(p12);\r
998 }\r
999 \r
1000 // PKCS12 の解放\r
1001 void FreePKCS12(PKCS12 *pkcs12)\r
1002 {\r
1003         // 引数チェック\r
1004         if (pkcs12 == NULL)\r
1005         {\r
1006                 return;\r
1007         }\r
1008 \r
1009         PKCS12_free(pkcs12);\r
1010 }\r
1011 \r
1012 // P12 を BUF に変換する\r
1013 BUF *P12ToBuf(P12 *p12)\r
1014 {\r
1015         BIO *bio;\r
1016         BUF *buf;\r
1017         // 引数チェック\r
1018         if (p12 == NULL)\r
1019         {\r
1020                 return NULL;\r
1021         }\r
1022 \r
1023         bio = P12ToBio(p12);\r
1024         if (bio == NULL)\r
1025         {\r
1026                 return NULL;\r
1027         }\r
1028 \r
1029         buf = BioToBuf(bio);\r
1030         FreeBio(bio);\r
1031 \r
1032         SeekBuf(buf, 0, 0);\r
1033 \r
1034         return buf;\r
1035 }\r
1036 \r
1037 // P12 を BIO に変換する\r
1038 BIO *P12ToBio(P12 *p12)\r
1039 {\r
1040         BIO *bio;\r
1041         // 引数チェック\r
1042         if (p12 == NULL)\r
1043         {\r
1044                 return NULL;\r
1045         }\r
1046 \r
1047         bio = NewBio();\r
1048         Lock(openssl_lock);\r
1049         {\r
1050                 i2d_PKCS12_bio(bio, p12->pkcs12);\r
1051         }\r
1052         Unlock(openssl_lock);\r
1053 \r
1054         return bio;\r
1055 }\r
1056 \r
1057 // BUF から P12 を読み込む\r
1058 P12 *BufToP12(BUF *b)\r
1059 {\r
1060         P12 *p12;\r
1061         BIO *bio;\r
1062         // 引数チェック\r
1063         if (b == NULL)\r
1064         {\r
1065                 return NULL;\r
1066         }\r
1067 \r
1068         bio = BufToBio(b);\r
1069         if (bio == NULL)\r
1070         {\r
1071                 return NULL;\r
1072         }\r
1073 \r
1074         p12 = BioToP12(bio);\r
1075         FreeBio(bio);\r
1076 \r
1077         return p12;\r
1078 }\r
1079 \r
1080 // BIO から P12 を読み込む\r
1081 P12 *BioToP12(BIO *bio)\r
1082 {\r
1083         PKCS12 *pkcs12;\r
1084         // 引数チェック\r
1085         if (bio == NULL)\r
1086         {\r
1087                 return NULL;\r
1088         }\r
1089 \r
1090         // 変換\r
1091         Lock(openssl_lock);\r
1092         {\r
1093                 pkcs12 = d2i_PKCS12_bio(bio, NULL);\r
1094         }\r
1095         Unlock(openssl_lock);\r
1096         if (pkcs12 == NULL)\r
1097         {\r
1098                 // 失敗\r
1099                 return NULL;\r
1100         }\r
1101 \r
1102         return PKCS12ToP12(pkcs12);\r
1103 }\r
1104 \r
1105 // PKCS12 から P12 を生成する\r
1106 P12 *PKCS12ToP12(PKCS12 *pkcs12)\r
1107 {\r
1108         P12 *p12;\r
1109         // 引数チェック\r
1110         if (pkcs12 == NULL)\r
1111         {\r
1112                 return NULL;\r
1113         }\r
1114 \r
1115         p12 = ZeroMalloc(sizeof(P12));\r
1116         p12->pkcs12 = pkcs12;\r
1117 \r
1118         return p12;\r
1119 }\r
1120 \r
1121 // バイナリを文字列に変換する\r
1122 char *ByteToStr(BYTE *src, UINT src_size)\r
1123 {\r
1124         UINT size;\r
1125         char *dst;\r
1126         UINT i;\r
1127         // 引数チェック\r
1128         if (src == NULL)\r
1129         {\r
1130                 return NULL;\r
1131         }\r
1132 \r
1133         size = MAX(src_size * 3, 1);\r
1134         dst = Malloc(size);\r
1135         dst[size - 1] = 0;\r
1136         for (i = 0;i < src_size;i++)\r
1137         {\r
1138                 char tmp[3];\r
1139                 Format(tmp, sizeof(tmp), "%02x", src[i]);\r
1140                 dst[i * 3 + 0] = tmp[0];\r
1141                 dst[i * 3 + 1] = tmp[1];\r
1142                 dst[i * 3 + 2] = ((i == (src_size - 1) ? 0 : ' '));\r
1143         }\r
1144 \r
1145         return dst;\r
1146 }\r
1147 \r
1148 // X_SERIAL の解放\r
1149 void FreeXSerial(X_SERIAL *serial)\r
1150 {\r
1151         // 引数チェック\r
1152         if (serial == NULL)\r
1153         {\r
1154                 return;\r
1155         }\r
1156 \r
1157         Free(serial->data);\r
1158         Free(serial);\r
1159 }\r
1160 \r
1161 // X_SERIAL の比較\r
1162 bool CompareXSerial(X_SERIAL *s1, X_SERIAL *s2)\r
1163 {\r
1164         // 引数チェック\r
1165         if (s1 == NULL || s2 == NULL)\r
1166         {\r
1167                 return false;\r
1168         }\r
1169 \r
1170         if (s1->size != s2->size)\r
1171         {\r
1172                 return false;\r
1173         }\r
1174 \r
1175         if (Cmp(s1->data, s2->data, s1->size) != 0)\r
1176         {\r
1177                 return false;\r
1178         }\r
1179 \r
1180         return true;\r
1181 }\r
1182 \r
1183 // X_SERIAL のコピー\r
1184 X_SERIAL *CloneXSerial(X_SERIAL *src)\r
1185 {\r
1186         X_SERIAL *s;\r
1187         // 引数チェック\r
1188         if (src == NULL)\r
1189         {\r
1190                 return NULL;\r
1191         }\r
1192 \r
1193         s = ZeroMalloc(sizeof(X_SERIAL));\r
1194         s->data = ZeroMalloc(src->size);\r
1195         Copy(s->data, src->data, src->size);\r
1196         s->size = src->size;\r
1197 \r
1198         return s;\r
1199 }\r
1200 \r
1201 // X_SERIAL の初期化\r
1202 X_SERIAL *NewXSerial(void *data, UINT size)\r
1203 {\r
1204         X_SERIAL *serial;\r
1205         UCHAR *buf = (UCHAR *)data;\r
1206         UINT i;\r
1207         // 引数チェック\r
1208         if (data == NULL || size == 0)\r
1209         {\r
1210                 return NULL;\r
1211         }\r
1212 \r
1213         for (i = 0;i < size;i++)\r
1214         {\r
1215                 if (buf[i] != 0)\r
1216                 {\r
1217                         break;\r
1218                 }\r
1219         }\r
1220         if (i == size)\r
1221         {\r
1222                 i = size - 1;\r
1223         }\r
1224         buf += i;\r
1225 \r
1226         serial = Malloc(sizeof(X_SERIAL));\r
1227         serial->size = size - i;\r
1228         serial->data = ZeroMalloc(size + 16);\r
1229         Copy(serial->data, buf, size - i);\r
1230 \r
1231         return serial;\r
1232 }\r
1233 \r
1234 // 2038 年 1 月 1 日までの日数を取得する\r
1235 UINT GetDaysUntil2038()\r
1236 {\r
1237         UINT64 now = SystemTime64();\r
1238         UINT64 target;\r
1239         SYSTEMTIME st;\r
1240 \r
1241         Zero(&st, sizeof(st));\r
1242         st.wYear = 2038;\r
1243         st.wMonth = 1;\r
1244         st.wDay = 1;\r
1245 \r
1246         target = SystemToUINT64(&st);\r
1247 \r
1248         if (now >= target)\r
1249         {\r
1250                 return 0;\r
1251         }\r
1252         else\r
1253         {\r
1254                 return (UINT)((target - now) / (UINT64)(1000 * 60 * 60 * 24));\r
1255         }\r
1256 }\r
1257 \r
1258 // X509 証明書を発行する\r
1259 X *NewX(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)\r
1260 {\r
1261         X509 *x509;\r
1262         X *x;\r
1263         // 引数チェック\r
1264         if (pub == NULL || priv == NULL || name == NULL || ca == NULL)\r
1265         {\r
1266                 return NULL;\r
1267         }\r
1268 \r
1269         x509 = NewX509(pub, priv, ca, name, days, serial);\r
1270         if (x509 == NULL)\r
1271         {\r
1272                 return NULL;\r
1273         }\r
1274 \r
1275         x = X509ToX(x509);\r
1276 \r
1277         if (x == NULL)\r
1278         {\r
1279                 return NULL;\r
1280         }\r
1281 \r
1282         return x;\r
1283 }\r
1284 \r
1285 // ルート証明書を作成する\r
1286 X *NewRootX(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)\r
1287 {\r
1288         X509 *x509;\r
1289         X *x, *x2;\r
1290         // 引数チェック\r
1291         if (pub == NULL || priv == NULL || name == NULL)\r
1292         {\r
1293                 return NULL;\r
1294         }\r
1295 \r
1296         x509 = NewRootX509(pub, priv, name, days, serial);\r
1297         if (x509 == NULL)\r
1298         {\r
1299                 return NULL;\r
1300         }\r
1301 \r
1302         x = X509ToX(x509);\r
1303         if (x == NULL)\r
1304         {\r
1305                 return NULL;\r
1306         }\r
1307 \r
1308         x2 = CloneX(x);\r
1309         FreeX(x);\r
1310 \r
1311         return x2;\r
1312 }\r
1313 \r
1314 // X509 証明書を発行する\r
1315 X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)\r
1316 {\r
1317         X509 *x509;\r
1318         UINT64 notBefore, notAfter;\r
1319         ASN1_TIME *t1, *t2;\r
1320         X509_NAME *subject_name, *issuer_name;\r
1321         // 引数チェック\r
1322         if (pub == NULL || name == NULL || ca == NULL)\r
1323         {\r
1324                 return NULL;\r
1325         }\r
1326         if (pub->private_key != false)\r
1327         {\r
1328                 return NULL;\r
1329         }\r
1330         if (priv->private_key == false)\r
1331         {\r
1332                 return NULL;\r
1333         }\r
1334 \r
1335         notBefore = SystemTime64();\r
1336         notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;\r
1337 \r
1338 \r
1339         // X509 の作成\r
1340         x509 = X509_new();\r
1341         if (x509 == NULL)\r
1342         {\r
1343                 return NULL;\r
1344         }\r
1345 \r
1346         // 有効期限の設定\r
1347         t1 = X509_get_notBefore(x509);\r
1348         t2 = X509_get_notAfter(x509);\r
1349         if (!UINT64ToAsn1Time(t1, notBefore))\r
1350         {\r
1351                 FreeX509(x509);\r
1352                 return NULL;\r
1353         }\r
1354         if (!UINT64ToAsn1Time(t2, notAfter))\r
1355         {\r
1356                 FreeX509(x509);\r
1357                 return NULL;\r
1358         }\r
1359 \r
1360         // 名前の設定\r
1361         subject_name = NameToX509Name(name);\r
1362         if (subject_name == NULL)\r
1363         {\r
1364                 FreeX509(x509);\r
1365                 return NULL;\r
1366         }\r
1367         issuer_name = X509_get_subject_name(ca->x509);\r
1368         if (issuer_name == NULL)\r
1369         {\r
1370                 FreeX509Name(subject_name);\r
1371                 FreeX509(x509);\r
1372                 return NULL;\r
1373         }\r
1374 \r
1375         X509_set_issuer_name(x509, issuer_name);\r
1376         X509_set_subject_name(x509, subject_name);\r
1377 \r
1378         FreeX509Name(subject_name);\r
1379 \r
1380         // シリアル番号の設定\r
1381         if (serial == NULL)\r
1382         {\r
1383                 char zero = 0;\r
1384                 ASN1_INTEGER *s = x509->cert_info->serialNumber;\r
1385                 OPENSSL_free(s->data);\r
1386                 s->data = OPENSSL_malloc(sizeof(char));\r
1387                 Copy(s->data, &zero, sizeof(char));\r
1388                 s->length = sizeof(char);\r
1389         }\r
1390         else\r
1391         {\r
1392                 ASN1_INTEGER *s = x509->cert_info->serialNumber;\r
1393                 OPENSSL_free(s->data);\r
1394                 s->data = OPENSSL_malloc(serial->size);\r
1395                 Copy(s->data, serial->data, serial->size);\r
1396                 s->length = serial->size;\r
1397         }\r
1398 \r
1399         Lock(openssl_lock);\r
1400         {\r
1401                 // 公開鍵の設定\r
1402                 X509_set_pubkey(x509, pub->pkey);\r
1403 \r
1404                 // 署名\r
1405                 X509_sign(x509, priv->pkey, EVP_sha1());\r
1406         }\r
1407         Unlock(openssl_lock);\r
1408 \r
1409         return x509;\r
1410 }\r
1411 \r
1412 // ルート X509 証明書を作成する\r
1413 X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)\r
1414 {\r
1415         X509 *x509;\r
1416         UINT64 notBefore, notAfter;\r
1417         ASN1_TIME *t1, *t2;\r
1418         X509_NAME *subject_name, *issuer_name;\r
1419         // 引数チェック\r
1420         if (pub == NULL || name == NULL || priv == NULL)\r
1421         {\r
1422                 return NULL;\r
1423         }\r
1424         if (days == 0)\r
1425         {\r
1426                 days = 365;\r
1427         }\r
1428         if (priv->private_key == false)\r
1429         {\r
1430                 return NULL;\r
1431         }\r
1432         if (pub->private_key != false)\r
1433         {\r
1434                 return NULL;\r
1435         }\r
1436 \r
1437         notBefore = SystemTime64();\r
1438         notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;\r
1439 \r
1440         // X509 の作成\r
1441         x509 = X509_new();\r
1442         if (x509 == NULL)\r
1443         {\r
1444                 return NULL;\r
1445         }\r
1446 \r
1447         // 有効期限の設定\r
1448         t1 = X509_get_notBefore(x509);\r
1449         t2 = X509_get_notAfter(x509);\r
1450         if (!UINT64ToAsn1Time(t1, notBefore))\r
1451         {\r
1452                 FreeX509(x509);\r
1453                 return NULL;\r
1454         }\r
1455         if (!UINT64ToAsn1Time(t2, notAfter))\r
1456         {\r
1457                 FreeX509(x509);\r
1458                 return NULL;\r
1459         }\r
1460 \r
1461         // 名前の設定\r
1462         subject_name = NameToX509Name(name);\r
1463         if (subject_name == NULL)\r
1464         {\r
1465                 FreeX509(x509);\r
1466                 return NULL;\r
1467         }\r
1468         issuer_name = NameToX509Name(name);\r
1469         if (issuer_name == NULL)\r
1470         {\r
1471                 FreeX509Name(subject_name);\r
1472                 FreeX509(x509);\r
1473                 return NULL;\r
1474         }\r
1475 \r
1476         X509_set_issuer_name(x509, issuer_name);\r
1477         X509_set_subject_name(x509, subject_name);\r
1478 \r
1479         FreeX509Name(subject_name);\r
1480         FreeX509Name(issuer_name);\r
1481 \r
1482         // シリアル番号の設定\r
1483         if (serial == NULL)\r
1484         {\r
1485                 char zero = 0;\r
1486                 ASN1_INTEGER *s = x509->cert_info->serialNumber;\r
1487                 OPENSSL_free(s->data);\r
1488                 s->data = OPENSSL_malloc(sizeof(char));\r
1489                 Copy(s->data, &zero, sizeof(char));\r
1490                 s->length = sizeof(char);\r
1491         }\r
1492         else\r
1493         {\r
1494                 ASN1_INTEGER *s = x509->cert_info->serialNumber;\r
1495                 OPENSSL_free(s->data);\r
1496                 s->data = OPENSSL_malloc(serial->size);\r
1497                 Copy(s->data, serial->data, serial->size);\r
1498                 s->length = serial->size;\r
1499         }\r
1500 \r
1501         Lock(openssl_lock);\r
1502         {\r
1503                 // 公開鍵の設定\r
1504                 X509_set_pubkey(x509, pub->pkey);\r
1505 \r
1506                 // 署名\r
1507                 X509_sign(x509, priv->pkey, EVP_sha1());\r
1508         }\r
1509         Unlock(openssl_lock);\r
1510 \r
1511         return x509;\r
1512 }\r
1513 \r
1514 // NAME を X509_NAME に変換\r
1515 void *NameToX509Name(NAME *nm)\r
1516 {\r
1517         X509_NAME *xn;\r
1518         // 引数チェック\r
1519         if (nm == NULL)\r
1520         {\r
1521                 return NULL;\r
1522         }\r
1523 \r
1524         xn = X509_NAME_new();\r
1525         if (xn == NULL)\r
1526         {\r
1527                 return NULL;\r
1528         }\r
1529 \r
1530         // エントリの追加\r
1531         AddX509Name(xn, NID_commonName, nm->CommonName);\r
1532         AddX509Name(xn, NID_organizationName, nm->Organization);\r
1533         AddX509Name(xn, NID_organizationalUnitName, nm->Unit);\r
1534         AddX509Name(xn, NID_countryName, nm->Country);\r
1535         AddX509Name(xn, NID_stateOrProvinceName, nm->State);\r
1536         AddX509Name(xn, NID_localityName, nm->Local);\r
1537 \r
1538         return xn;\r
1539 }\r
1540 \r
1541 // X509_NAME にエントリを追加する\r
1542 bool AddX509Name(void *xn, int nid, wchar_t *str)\r
1543 {\r
1544         X509_NAME *x509_name;\r
1545         UINT utf8_size;\r
1546         BYTE *utf8;\r
1547         // 引数チェック\r
1548         if (xn == NULL || str == NULL)\r
1549         {\r
1550                 return false;\r
1551         }\r
1552 \r
1553         // UTF-8 に変換\r
1554         utf8_size = CalcUniToUtf8(str);\r
1555         if (utf8_size == 0)\r
1556         {\r
1557                 return false;\r
1558         }\r
1559         utf8 = ZeroMalloc(utf8_size + 1);\r
1560         UniToUtf8(utf8, utf8_size, str);\r
1561         utf8[utf8_size] = 0;\r
1562 \r
1563         // 追加\r
1564         x509_name = (X509_NAME *)xn;\r
1565         Lock(openssl_lock);\r
1566         {\r
1567                 X509_NAME_add_entry_by_NID(x509_name, nid, MBSTRING_ASC, utf8, utf8_size, -1, 0);\r
1568         }\r
1569         Unlock(openssl_lock);\r
1570         Free(utf8);\r
1571 \r
1572         return true;\r
1573 }\r
1574 \r
1575 // X509_NAME を解放\r
1576 void FreeX509Name(void *xn)\r
1577 {\r
1578         X509_NAME *x509_name;\r
1579         // 引数チェック\r
1580         if (xn == NULL)\r
1581         {\r
1582                 return;\r
1583         }\r
1584 \r
1585         x509_name = (X509_NAME *)xn;\r
1586         X509_NAME_free(x509_name);\r
1587 }\r
1588 \r
1589 // NAME の作成\r
1590 NAME *NewName(wchar_t *common_name, wchar_t *organization, wchar_t *unit,\r
1591                           wchar_t *country, wchar_t *state, wchar_t *local)\r
1592 {\r
1593         NAME *nm = ZeroMalloc(sizeof(NAME));\r
1594 \r
1595         if (UniIsEmptyStr(common_name) == false)\r
1596         {\r
1597                 nm->CommonName = CopyUniStr(common_name);\r
1598         }\r
1599 \r
1600         if (UniIsEmptyStr(organization) == false)\r
1601         {\r
1602                 nm->Organization = CopyUniStr(organization);\r
1603         }\r
1604 \r
1605         if (UniIsEmptyStr(unit) == false)\r
1606         {\r
1607                 nm->Unit = CopyUniStr(unit);\r
1608         }\r
1609 \r
1610         if (UniIsEmptyStr(country) == false)\r
1611         {\r
1612                 nm->Country = CopyUniStr(country);\r
1613         }\r
1614 \r
1615         if (UniIsEmptyStr(state) == false)\r
1616         {\r
1617                 nm->State = CopyUniStr(state);\r
1618         }\r
1619 \r
1620         if (UniIsEmptyStr(local) == false)\r
1621         {\r
1622                 nm->Local = CopyUniStr(local);\r
1623         }\r
1624 \r
1625         return nm;\r
1626 }\r
1627 \r
1628 // 証明書の有効期限を現在時刻で確認する\r
1629 bool CheckXDateNow(X *x)\r
1630 {\r
1631         // 引数チェック\r
1632         if (x == NULL)\r
1633         {\r
1634                 return false;\r
1635         }\r
1636 \r
1637         return CheckXDate(x, SystemTime64());\r
1638 }\r
1639 \r
1640 // 証明書の有効期限を確認する\r
1641 bool CheckXDate(X *x, UINT64 current_system_time)\r
1642 {\r
1643         // 引数チェック\r
1644         if (x == NULL)\r
1645         {\r
1646                 return false;\r
1647         }\r
1648 \r
1649         if (x->notBefore >= current_system_time || x->notAfter <= current_system_time)\r
1650         {\r
1651                 return false;\r
1652         }\r
1653         return true;\r
1654 }\r
1655 \r
1656 // 証明書の有効期限情報を読み込む\r
1657 void LoadXDates(X *x)\r
1658 {\r
1659         // 引数チェック\r
1660         if (x == NULL)\r
1661         {\r
1662                 return;\r
1663         }\r
1664 \r
1665         x->notBefore = Asn1TimeToUINT64(x->x509->cert_info->validity->notBefore);\r
1666         x->notAfter = Asn1TimeToUINT64(x->x509->cert_info->validity->notAfter);\r
1667 }\r
1668 \r
1669 // 64bit システム時刻を ASN1 時刻に変換する\r
1670 bool UINT64ToAsn1Time(void *asn1_time, UINT64 t)\r
1671 {\r
1672         SYSTEMTIME st;\r
1673         // 引数チェック\r
1674         if (asn1_time == NULL)\r
1675         {\r
1676                 return false;\r
1677         }\r
1678 \r
1679         UINT64ToSystem(&st, t);\r
1680         return SystemToAsn1Time(asn1_time, &st);\r
1681 }\r
1682 \r
1683 // システム時刻を ASN1 時刻に変換する\r
1684 bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s)\r
1685 {\r
1686         char tmp[20];\r
1687         ASN1_TIME *t;\r
1688         // 引数チェック\r
1689         if (asn1_time == NULL || s == NULL)\r
1690         {\r
1691                 return false;\r
1692         }\r
1693 \r
1694         if (SystemToStr(tmp, sizeof(tmp), s) == false)\r
1695         {\r
1696                 return false;\r
1697         }\r
1698         t = (ASN1_TIME *)asn1_time;\r
1699         if (t->data == NULL || t->length < sizeof(tmp))\r
1700         {\r
1701                 t->data = OPENSSL_malloc(sizeof(tmp));\r
1702         }\r
1703         StrCpy((char *)t->data, t->length, tmp);\r
1704         t->length = StrLen(tmp);\r
1705         t->type = V_ASN1_UTCTIME;\r
1706 \r
1707         return true;\r
1708 }\r
1709 \r
1710 // システム時刻を文字列に変換する\r
1711 bool SystemToStr(char *str, UINT size, SYSTEMTIME *s)\r
1712 {\r
1713         // 引数チェック\r
1714         if (str == NULL || s == NULL)\r
1715         {\r
1716                 return false;\r
1717         }\r
1718 \r
1719         Format(str, size, "%02u%02u%02u%02u%02u%02uZ",\r
1720                 s->wYear % 100, s->wMonth, s->wDay,\r
1721                 s->wHour, s->wMinute, s->wSecond);\r
1722 \r
1723         return true;\r
1724 }\r
1725 \r
1726 // ASN1 時刻を UINT64 時刻に変換する\r
1727 UINT64 Asn1TimeToUINT64(void *asn1_time)\r
1728 {\r
1729         SYSTEMTIME st;\r
1730         // 引数チェック\r
1731         if (asn1_time == NULL)\r
1732         {\r
1733                 return 0;\r
1734         }\r
1735 \r
1736         if (Asn1TimeToSystem(&st, asn1_time) == false)\r
1737         {\r
1738                 return 0;\r
1739         }\r
1740         return SystemToUINT64(&st);\r
1741 }\r
1742 \r
1743 // ASN1 時刻をシステム時刻に変換する\r
1744 bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time)\r
1745 {\r
1746         ASN1_TIME *t;\r
1747         // 引数チェック\r
1748         if (s == NULL || asn1_time == NULL)\r
1749         {\r
1750                 return false;\r
1751         }\r
1752 \r
1753         t = (ASN1_TIME *)asn1_time;\r
1754         if (StrToSystem(s, (char *)t->data) == false)\r
1755         {\r
1756                 return false;\r
1757         }\r
1758 \r
1759         if (t->type == V_ASN1_GENERALIZEDTIME)\r
1760         {\r
1761                 LocalToSystem(s, s);\r
1762         }\r
1763 \r
1764         return true;\r
1765 }\r
1766 \r
1767 // 文字列をシステム時刻に変換する\r
1768 bool StrToSystem(SYSTEMTIME *s, char *str)\r
1769 {\r
1770         // 引数チェック\r
1771         if (s == NULL || str == NULL)\r
1772         {\r
1773                 return false;\r
1774         }\r
1775         if (StrLen(str) != 13)\r
1776         {\r
1777                 return false;\r
1778         }\r
1779         if (str[12] != 'Z')\r
1780         {\r
1781                 return false;\r
1782         }\r
1783 \r
1784         // 変換\r
1785         {\r
1786                 char year[3] = {str[0], str[1], 0},\r
1787                         month[3] = {str[2], str[3], 0},\r
1788                         day[3] = {str[4], str[5], 0},\r
1789                         hour[3] = {str[6], str[7], 0},\r
1790                         minute[3] = {str[8], str[9], 0},\r
1791                         second[3] = {str[10], str[11], 0};\r
1792                 Zero(s, sizeof(SYSTEMTIME));\r
1793                 s->wYear = ToInt(year);\r
1794                 if (s->wYear >= 60)\r
1795                 {\r
1796                         s->wYear += 1900;\r
1797                 }\r
1798                 else\r
1799                 {\r
1800                         s->wYear += 2000;\r
1801                 }\r
1802                 s->wMonth = ToInt(month);\r
1803                 s->wDay = ToInt(day);\r
1804                 s->wHour = ToInt(hour);\r
1805                 s->wMinute = ToInt(minute);\r
1806                 s->wSecond = ToInt(second);\r
1807                 NormalizeSystem(s);\r
1808         }\r
1809 \r
1810         return true;\r
1811 }\r
1812 \r
1813 // RSA 署名の検査\r
1814 bool RsaVerify(void *data, UINT data_size, void *sign, K *k)\r
1815 {\r
1816         return RsaVerifyEx(data, data_size, sign, k, 0);\r
1817 }\r
1818 bool RsaVerifyEx(void *data, UINT data_size, void *sign, K *k, UINT bits)\r
1819 {\r
1820         UCHAR hash_data[SIGN_HASH_SIZE];\r
1821         UCHAR decrypt_data[SIGN_HASH_SIZE];\r
1822         // 引数チェック\r
1823         if (data == NULL || sign == NULL || k == NULL || k->private_key != false)\r
1824         {\r
1825                 return false;\r
1826         }\r
1827         if (bits == 0)\r
1828         {\r
1829                 bits = 1024;\r
1830         }\r
1831 \r
1832         // データをハッシュ\r
1833         if (HashForSign(hash_data, sizeof(hash_data), data, data_size) == false)\r
1834         {\r
1835                 return false;\r
1836         }\r
1837 \r
1838         // 署名を解読\r
1839         if (RSA_public_decrypt(bits / 8, sign, decrypt_data, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)\r
1840         {\r
1841                 return false;\r
1842         }\r
1843 \r
1844         // 比較\r
1845         if (Cmp(decrypt_data, hash_data, sizeof(SIGN_HASH_SIZE)) != 0)\r
1846         {\r
1847                 return false;\r
1848         }\r
1849 \r
1850         return true;\r
1851 }\r
1852 \r
1853 // RSA 署名\r
1854 bool RsaSign(void *dst, void *src, UINT size, K *k)\r
1855 {\r
1856         return RsaSignEx(dst, src, size, k, 0);\r
1857 }\r
1858 bool RsaSignEx(void *dst, void *src, UINT size, K *k, UINT bits)\r
1859 {\r
1860         UCHAR hash[SIGN_HASH_SIZE];\r
1861         // 引数チェック\r
1862         if (dst == NULL || src == NULL || k == NULL || k->pkey->type != EVP_PKEY_RSA)\r
1863         {\r
1864                 return false;\r
1865         }\r
1866         if (bits == 0)\r
1867         {\r
1868                 bits = 1024;\r
1869         }\r
1870 \r
1871         Zero(dst, bits / 8);\r
1872 \r
1873         // ハッシュ\r
1874         if (HashForSign(hash, sizeof(hash), src, size) == false)\r
1875         {\r
1876                 return false;\r
1877         }\r
1878 \r
1879         // 署名\r
1880         if (RSA_private_encrypt(sizeof(hash), hash, dst, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)\r
1881         {\r
1882                 return false;\r
1883         }\r
1884 \r
1885         return true;\r
1886 }\r
1887 \r
1888 // SHA-1 による署名データの生成\r
1889 bool HashForSign(void *dst, UINT dst_size, void *src, UINT src_size)\r
1890 {\r
1891         UCHAR *buf = (UCHAR *)dst;\r
1892         UCHAR sign_data[] =\r
1893         {\r
1894                 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E,\r
1895                 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,\r
1896         };\r
1897         // 引数チェック\r
1898         if (dst == NULL || src == NULL || src_size == 0 || MIN_SIGN_HASH_SIZE > dst_size)\r
1899         {\r
1900                 return false;\r
1901         }\r
1902 \r
1903         // ヘッダ部分\r
1904         Copy(buf, sign_data, sizeof(sign_data));\r
1905 \r
1906         // ハッシュ\r
1907         HashSha1(HASHED_DATA(buf), src, src_size);\r
1908 \r
1909         return true;\r
1910 }\r
1911 \r
1912 // RSA 公開鍵による復号化\r
1913 bool RsaPublicDecrypt(void *dst, void *src, UINT size, K *k)\r
1914 {\r
1915         void *tmp;\r
1916         int ret;\r
1917         // 引数チェック\r
1918         if (src == NULL || size == 0 || k == NULL)\r
1919         {\r
1920                 return false;\r
1921         }\r
1922 \r
1923         tmp = ZeroMalloc(size);\r
1924         Lock(openssl_lock);\r
1925         {\r
1926                 ret = RSA_public_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);\r
1927         }\r
1928         Unlock(openssl_lock);\r
1929         if (ret <= 0)\r
1930         {\r
1931 /*              Debug("RSA Error: 0x%x\n",\r
1932                         ERR_get_error());\r
1933 */              Free(tmp);\r
1934                 return false;\r
1935         }\r
1936 \r
1937         Copy(dst, tmp, size);\r
1938         Free(tmp);\r
1939 \r
1940         return true;\r
1941 }\r
1942 \r
1943 // RSA 秘密鍵による暗号化\r
1944 bool RsaPrivateEncrypt(void *dst, void *src, UINT size, K *k)\r
1945 {\r
1946         void *tmp;\r
1947         int ret;\r
1948         // 引数チェック\r
1949         if (src == NULL || size == 0 || k == NULL)\r
1950         {\r
1951                 return false;\r
1952         }\r
1953 \r
1954         tmp = ZeroMalloc(size);\r
1955         Lock(openssl_lock);\r
1956         {\r
1957                 ret = RSA_private_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);\r
1958         }\r
1959         Unlock(openssl_lock);\r
1960         if (ret <= 0)\r
1961         {\r
1962 /*              Debug("RSA Error: %u\n",\r
1963                         ERR_GET_REASON(ERR_get_error()));\r
1964 */              Free(tmp);\r
1965                 return false;\r
1966         }\r
1967 \r
1968         Copy(dst, tmp, size);\r
1969         Free(tmp);\r
1970 \r
1971         return true;\r
1972 }\r
1973 \r
1974 // RSA 秘密鍵による復号化\r
1975 bool RsaPrivateDecrypt(void *dst, void *src, UINT size, K *k)\r
1976 {\r
1977         void *tmp;\r
1978         int ret;\r
1979         // 引数チェック\r
1980         if (src == NULL || size == 0 || k == NULL)\r
1981         {\r
1982                 return false;\r
1983         }\r
1984 \r
1985         tmp = ZeroMalloc(size);\r
1986         Lock(openssl_lock);\r
1987         {\r
1988                 ret = RSA_private_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);\r
1989         }\r
1990         Unlock(openssl_lock);\r
1991         if (ret <= 0)\r
1992         {\r
1993                 return false;\r
1994         }\r
1995 \r
1996         Copy(dst, tmp, size);\r
1997         Free(tmp);\r
1998 \r
1999         return true;\r
2000 }\r
2001 \r
2002 // RSA 公開鍵による暗号化\r
2003 bool RsaPublicEncrypt(void *dst, void *src, UINT size, K *k)\r
2004 {\r
2005         void *tmp;\r
2006         int ret;\r
2007         // 引数チェック\r
2008         if (src == NULL || size == 0 || k == NULL)\r
2009         {\r
2010                 return false;\r
2011         }\r
2012 \r
2013         tmp = ZeroMalloc(size);\r
2014         Lock(openssl_lock);\r
2015         {\r
2016                 ret = RSA_public_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);\r
2017         }\r
2018         Unlock(openssl_lock);\r
2019         if (ret <= 0)\r
2020         {\r
2021                 return false;\r
2022         }\r
2023 \r
2024         Copy(dst, tmp, size);\r
2025         Free(tmp);\r
2026 \r
2027         return true;\r
2028 }\r
2029 \r
2030 // RSA 動作環境チェック\r
2031 bool RsaCheckEx()\r
2032 {\r
2033         UINT num = 20;\r
2034         UINT i;\r
2035 \r
2036         for (i = 0;i < num;i++)\r
2037         {\r
2038                 if (RsaCheck())\r
2039                 {\r
2040                         return true;\r
2041                 }\r
2042 \r
2043                 SleepThread(100);\r
2044         }\r
2045 \r
2046         return false;\r
2047 }\r
2048 bool RsaCheck()\r
2049 {\r
2050         RSA *rsa;\r
2051         K *priv_key, *pub_key;\r
2052         BIO *bio;\r
2053         char errbuf[MAX_SIZE];\r
2054         UINT size = 0;\r
2055         UINT bit = 32;\r
2056         // 引数チェック\r
2057 \r
2058         // 鍵生成\r
2059         Lock(openssl_lock);\r
2060         {\r
2061                 rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);\r
2062         }\r
2063         Unlock(openssl_lock);\r
2064         if (rsa == NULL)\r
2065         {\r
2066                 Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));\r
2067                 return false;\r
2068         }\r
2069 \r
2070         // 秘密鍵\r
2071         bio = NewBio();\r
2072         Lock(openssl_lock);\r
2073         {\r
2074                 i2d_RSAPrivateKey_bio(bio, rsa);\r
2075         }\r
2076         Unlock(openssl_lock);\r
2077         BIO_seek(bio, 0);\r
2078         priv_key = BioToK(bio, true, false, NULL);\r
2079         FreeBio(bio);\r
2080 \r
2081         // 公開鍵\r
2082         bio = NewBio();\r
2083         Lock(openssl_lock);\r
2084         {\r
2085                 i2d_RSA_PUBKEY_bio(bio, rsa);\r
2086         }\r
2087         Unlock(openssl_lock);\r
2088         BIO_seek(bio, 0);\r
2089         pub_key = BioToK(bio, false, false, NULL);\r
2090         FreeBio(bio);\r
2091 \r
2092         RSA_free(rsa);\r
2093 \r
2094         size = RsaPublicSize(pub_key);\r
2095 \r
2096         if (size != ((bit + 7) / 8))\r
2097         {\r
2098                 FreeK(priv_key);\r
2099                 FreeK(pub_key);\r
2100 \r
2101                 return false;\r
2102         }\r
2103 \r
2104         FreeK(priv_key);\r
2105         FreeK(pub_key);\r
2106 \r
2107         return true;\r
2108 }\r
2109 \r
2110 // RSA 鍵の生成\r
2111 bool RsaGen(K **priv, K **pub, UINT bit)\r
2112 {\r
2113         RSA *rsa;\r
2114         K *priv_key, *pub_key;\r
2115         BIO *bio;\r
2116         char errbuf[MAX_SIZE];\r
2117         UINT size = 0;\r
2118         // 引数チェック\r
2119         if (priv == NULL || pub == NULL)\r
2120         {\r
2121                 return false;\r
2122         }\r
2123         if (bit == 0)\r
2124         {\r
2125                 bit = 1024;\r
2126         }\r
2127 \r
2128         // 鍵生成\r
2129         Lock(openssl_lock);\r
2130         {\r
2131                 rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);\r
2132         }\r
2133         Unlock(openssl_lock);\r
2134         if (rsa == NULL)\r
2135         {\r
2136                 Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));\r
2137                 return false;\r
2138         }\r
2139 \r
2140         // 秘密鍵\r
2141         bio = NewBio();\r
2142         Lock(openssl_lock);\r
2143         {\r
2144                 i2d_RSAPrivateKey_bio(bio, rsa);\r
2145         }\r
2146         Unlock(openssl_lock);\r
2147         BIO_seek(bio, 0);\r
2148         priv_key = BioToK(bio, true, false, NULL);\r
2149         FreeBio(bio);\r
2150 \r
2151         // 公開鍵\r
2152         bio = NewBio();\r
2153         Lock(openssl_lock);\r
2154         {\r
2155                 i2d_RSA_PUBKEY_bio(bio, rsa);\r
2156         }\r
2157         Unlock(openssl_lock);\r
2158         BIO_seek(bio, 0);\r
2159         pub_key = BioToK(bio, false, false, NULL);\r
2160         FreeBio(bio);\r
2161 \r
2162         *priv = priv_key;\r
2163         *pub = pub_key;\r
2164 \r
2165         RSA_free(rsa);\r
2166 \r
2167         size = RsaPublicSize(*pub);\r
2168 \r
2169         if (size != ((bit + 7) / 8))\r
2170         {\r
2171                 FreeK(*priv);\r
2172                 FreeK(*pub);\r
2173 \r
2174                 return RsaGen(priv, pub, bit);\r
2175         }\r
2176 \r
2177         return true;\r
2178 }\r
2179 \r
2180 // 証明書 X が証明書 x_issuer の発行者によって署名されているかどうか確認する\r
2181 bool CheckX(X *x, X *x_issuer)\r
2182 {\r
2183         K *k;\r
2184         bool ret;\r
2185         // 引数チェック\r
2186         if (x == NULL || x_issuer == NULL)\r
2187         {\r
2188                 return false;\r
2189         }\r
2190 \r
2191         k = GetKFromX(x_issuer);\r
2192         if (k == NULL)\r
2193         {\r
2194                 return false;\r
2195         }\r
2196 \r
2197         ret = CheckSignature(x, k);\r
2198         FreeK(k);\r
2199 \r
2200         return ret;\r
2201 }\r
2202 \r
2203 // 証明書 X の署名を公開鍵 K で確認する\r
2204 bool CheckSignature(X *x, K *k)\r
2205 {\r
2206         // 引数チェック\r
2207         if (x == NULL || k == NULL)\r
2208         {\r
2209                 return false;\r
2210         }\r
2211 \r
2212         Lock(openssl_lock);\r
2213         {\r
2214                 if (X509_verify(x->x509, k->pkey) == 0)\r
2215                 {\r
2216                         Unlock(openssl_lock);\r
2217                         return false;\r
2218                 }\r
2219         }\r
2220         Unlock(openssl_lock);\r
2221         return true;\r
2222 }\r
2223 \r
2224 // 証明書から公開鍵を取得する\r
2225 K *GetKFromX(X *x)\r
2226 {\r
2227         EVP_PKEY *pkey;\r
2228         K *k;\r
2229         // 引数チェック\r
2230         if (x == NULL)\r
2231         {\r
2232                 return NULL;\r
2233         }\r
2234 \r
2235         Lock(openssl_lock);\r
2236         {\r
2237                 pkey = X509_get_pubkey(x->x509);\r
2238         }\r
2239         Unlock(openssl_lock);\r
2240         if (pkey == NULL)\r
2241         {\r
2242                 return NULL;\r
2243         }\r
2244 \r
2245         k = ZeroMalloc(sizeof(K));\r
2246         k->pkey = pkey;\r
2247 \r
2248         return k;\r
2249 }\r
2250 \r
2251 // 名前の比較\r
2252 bool CompareName(NAME *n1, NAME *n2)\r
2253 {\r
2254         // 引数チェック\r
2255         if (n1 == NULL || n2 == NULL)\r
2256         {\r
2257                 return false;\r
2258         }\r
2259 \r
2260         // 名前比較\r
2261         if (UniStrCmpi(n1->CommonName, n2->CommonName) == 0 &&\r
2262                 UniStrCmpi(n1->Organization, n2->Organization) == 0 &&\r
2263                 UniStrCmpi(n1->Unit, n2->Unit) == 0 &&\r
2264                 UniStrCmpi(n1->Country, n2->Country) == 0 &&\r
2265                 UniStrCmpi(n1->State, n2->State) == 0 &&\r
2266                 UniStrCmpi(n1->Local, n2->Local) == 0)\r
2267         {\r
2268                 return true;\r
2269         }\r
2270 \r
2271         return false;\r
2272 }\r
2273 \r
2274 // X の名前の解放\r
2275 void FreeXNames(X *x)\r
2276 {\r
2277         // 引数チェック\r
2278         if (x == NULL)\r
2279         {\r
2280                 return;\r
2281         }\r
2282 \r
2283         FreeName(x->issuer_name);\r
2284         x->issuer_name = NULL;\r
2285 \r
2286         FreeName(x->subject_name);\r
2287         x->subject_name = NULL;\r
2288 }\r
2289 \r
2290 // 名前の解放\r
2291 void FreeName(NAME *n)\r
2292 {\r
2293         // 引数チェック\r
2294         if (n == NULL)\r
2295         {\r
2296                 return;\r
2297         }\r
2298 \r
2299         // 文字列を解放\r
2300         Free(n->CommonName);\r
2301         Free(n->Organization);\r
2302         Free(n->Unit);\r
2303         Free(n->Country);\r
2304         Free(n->State);\r
2305         Free(n->Local);\r
2306 \r
2307         // オブジェクトを解放\r
2308         Free(n);\r
2309 \r
2310         return;\r
2311 }\r
2312 \r
2313 // 証明書の名前を取得する\r
2314 void LoadXNames(X *x)\r
2315 {\r
2316         X509 *x509;\r
2317         // 引数チェック\r
2318         if (x == NULL)\r
2319         {\r
2320                 return;\r
2321         }\r
2322 \r
2323         x509 = x->x509;\r
2324         x->issuer_name = X509NameToName(X509_get_issuer_name(x509));\r
2325         x->subject_name = X509NameToName(X509_get_subject_name(x509));\r
2326 }\r
2327 \r
2328 // X509_NAME 構造体を NAME 構造体に変換\r
2329 NAME *X509NameToName(void *xn)\r
2330 {\r
2331         NAME *n;\r
2332         // 引数チェック\r
2333         if (xn == NULL)\r
2334         {\r
2335                 return NULL;\r
2336         }\r
2337 \r
2338         n = ZeroMalloc(sizeof(NAME));\r
2339 \r
2340         // 文字列を順番に取得する\r
2341         n->CommonName = GetUniStrFromX509Name(xn, NID_commonName);\r
2342         n->Organization = GetUniStrFromX509Name(xn, NID_organizationName);\r
2343         n->Unit = GetUniStrFromX509Name(xn, NID_organizationalUnitName);\r
2344         n->Country = GetUniStrFromX509Name(xn, NID_countryName);\r
2345         n->State = GetUniStrFromX509Name(xn, NID_stateOrProvinceName);\r
2346         n->Local = GetUniStrFromX509Name(xn, NID_localityName);\r
2347 \r
2348         return n;\r
2349 }\r
2350 \r
2351 // X509_NAME 構造体の中から Unicode 文字列を読み込む\r
2352 wchar_t *GetUniStrFromX509Name(void *xn, int nid)\r
2353 {\r
2354         UCHAR txt[1024];\r
2355         bool b = false;\r
2356         UINT i, size;\r
2357         int index;\r
2358         bool unicode = false;\r
2359         bool is_utf_8 = false;\r
2360         ASN1_OBJECT *obj;\r
2361         ASN1_STRING *data;\r
2362         // 引数チェック\r
2363         if (xn == NULL || nid == 0)\r
2364         {\r
2365                 return NULL;\r
2366         }\r
2367 \r
2368         Zero(txt, sizeof(txt));\r
2369         if (X509_NAME_get_text_by_NID(xn, nid, (char *)txt, sizeof(txt) - 2) <= 0)\r
2370         {\r
2371                 return NULL;\r
2372         }\r
2373 \r
2374         obj = OBJ_nid2obj(nid);\r
2375         if (obj == NULL)\r
2376         {\r
2377                 return NULL;\r
2378         }\r
2379         index = X509_NAME_get_index_by_OBJ(xn, obj, -1);\r
2380         if (index < 0)\r
2381         {\r
2382                 return NULL;\r
2383         }\r
2384         data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(xn, index));\r
2385         if (data == NULL)\r
2386         {\r
2387                 return NULL;\r
2388         }\r
2389         if (data->type == V_ASN1_BMPSTRING)\r
2390         {\r
2391                 unicode = true;\r
2392         }\r
2393         if (data->type == V_ASN1_UTF8STRING || data->type == V_ASN1_T61STRING)\r
2394         {\r
2395                 is_utf_8 = true;\r
2396         }\r
2397 \r
2398         size = UniStrLen((wchar_t *)txt) * 4 + 8;\r
2399         for (i = 0;i < size;i++)\r
2400         {\r
2401                 if (txt[i] >= 0x80)\r
2402                 {\r
2403                         unicode = true;\r
2404                         break;\r
2405                 }\r
2406         }\r
2407 \r
2408         if (is_utf_8)\r
2409         {\r
2410                 wchar_t *ret;\r
2411                 UINT ret_size;\r
2412 \r
2413                 ret_size = CalcUtf8ToUni(txt, StrLen(txt));\r
2414                 ret = ZeroMalloc(ret_size + 8);\r
2415                 Utf8ToUni(ret, ret_size, txt, StrLen(txt));\r
2416 \r
2417                 return ret;\r
2418         }\r
2419         else if (unicode == false)\r
2420         {\r
2421                 wchar_t tmp[1024];\r
2422                 StrToUni(tmp, sizeof(tmp), (char *)txt);\r
2423                 return CopyUniStr(tmp);\r
2424         }\r
2425         else\r
2426         {\r
2427                 EndianUnicode((wchar_t *)txt);\r
2428                 return CopyUniStr((wchar_t *)txt);\r
2429         }\r
2430 }\r
2431 \r
2432 // 証明書 x1 と x2 が等しいかどうかチェックする\r
2433 bool CompareX(X *x1, X *x2)\r
2434 {\r
2435         // 引数チェック\r
2436         if (x1 == NULL || x2 == NULL)\r
2437         {\r
2438                 return false;\r
2439         }\r
2440 \r
2441         Lock(openssl_lock);\r
2442         if (X509_cmp(x1->x509, x2->x509) == 0)\r
2443         {\r
2444                 Unlock(openssl_lock);\r
2445                 return true;\r
2446         }\r
2447         else\r
2448         {\r
2449                 Unlock(openssl_lock);\r
2450                 return false;\r
2451         }\r
2452 }\r
2453 \r
2454 // K が X の秘密鍵かどうかチェックする\r
2455 bool CheckXandK(X *x, K *k)\r
2456 {\r
2457         // 引数チェック\r
2458         if (x == NULL || k == NULL)\r
2459         {\r
2460                 return false;\r
2461         }\r
2462 \r
2463         Lock(openssl_lock);\r
2464         if (X509_check_private_key(x->x509, k->pkey) != 0)\r
2465         {\r
2466                 Unlock(openssl_lock);\r
2467                 return true;\r
2468         }\r
2469         else\r
2470         {\r
2471                 Unlock(openssl_lock);\r
2472                 return false;\r
2473         }\r
2474 }\r
2475 \r
2476 // ファイルから X を読み込む\r
2477 X *FileToX(char *filename)\r
2478 {\r
2479         wchar_t *filename_w = CopyStrToUni(filename);\r
2480         X *ret = FileToXW(filename_w);\r
2481 \r
2482         Free(filename_w);\r
2483 \r
2484         return ret;\r
2485 }\r
2486 X *FileToXW(wchar_t *filename)\r
2487 {\r
2488         bool text;\r
2489         BUF *b;\r
2490         X *x;\r
2491         // 引数チェック\r
2492         if (filename == NULL)\r
2493         {\r
2494                 return NULL;\r
2495         }\r
2496 \r
2497         b = ReadDumpW(filename);\r
2498         text = IsBase64(b);\r
2499 \r
2500         x = BufToX(b, text);\r
2501         FreeBuf(b);\r
2502 \r
2503         return x;\r
2504 }\r
2505 \r
2506 // X をファイルに書き出す\r
2507 bool XToFile(X *x, char *filename, bool text)\r
2508 {\r
2509         wchar_t *filename_w = CopyStrToUni(filename);\r
2510         bool ret = XToFileW(x, filename_w, text);\r
2511 \r
2512         Free(filename_w);\r
2513 \r
2514         return ret;\r
2515 }\r
2516 bool XToFileW(X *x, wchar_t *filename, bool text)\r
2517 {\r
2518         BUF *b;\r
2519         bool ret;\r
2520         // 引数チェック\r
2521         if (x == NULL || filename == NULL)\r
2522         {\r
2523                 return false;\r
2524         }\r
2525 \r
2526         b = XToBuf(x, text);\r
2527         if (b == NULL)\r
2528         {\r
2529                 return false;\r
2530         }\r
2531 \r
2532         ret = DumpBufW(b, filename);\r
2533         FreeBuf(b);\r
2534 \r
2535         return ret;\r
2536 }\r
2537 \r
2538 // ファイルから K を読み込む\r
2539 K *FileToK(char *filename, bool private_key, char *password)\r
2540 {\r
2541         wchar_t *filename_w = CopyStrToUni(filename);\r
2542         K *ret;\r
2543 \r
2544         ret = FileToKW(filename_w, private_key, password);\r
2545 \r
2546         Free(filename_w);\r
2547 \r
2548         return ret;\r
2549 }\r
2550 K *FileToKW(wchar_t *filename, bool private_key, char *password)\r
2551 {\r
2552         bool text;\r
2553         BUF *b;\r
2554         K *k;\r
2555         // 引数チェック\r
2556         if (filename == NULL)\r
2557         {\r
2558                 return NULL;\r
2559         }\r
2560 \r
2561         b = ReadDumpW(filename);\r
2562         if (b == NULL)\r
2563         {\r
2564                 return NULL;\r
2565         }\r
2566 \r
2567         text = IsBase64(b);\r
2568         if (text == false)\r
2569         {\r
2570                 k = BufToK(b, private_key, false, NULL);\r
2571         }\r
2572         else\r
2573         {\r
2574                 k = BufToK(b, private_key, true, NULL);\r
2575                 if (k == NULL)\r
2576                 {\r
2577                         k = BufToK(b, private_key, true, password);\r
2578                 }\r
2579         }\r
2580 \r
2581         FreeBuf(b);\r
2582 \r
2583         return k;\r
2584 }\r
2585 \r
2586 // K をファイルに保存する\r
2587 bool KToFile(K *k, char *filename, bool text, char *password)\r
2588 {\r
2589         wchar_t *filename_w = CopyStrToUni(filename);\r
2590         bool ret = KToFileW(k, filename_w, text, password);\r
2591 \r
2592         Free(filename_w);\r
2593 \r
2594         return ret;\r
2595 }\r
2596 bool KToFileW(K *k, wchar_t *filename, bool text, char *password)\r
2597 {\r
2598         BUF *b;\r
2599         bool ret;\r
2600         // 引数チェック\r
2601         if (k == NULL || filename == NULL)\r
2602         {\r
2603                 return false;\r
2604         }\r
2605 \r
2606         b = KToBuf(k, text, password);\r
2607         if (b == NULL)\r
2608         {\r
2609                 return false;\r
2610         }\r
2611 \r
2612         ret = DumpBufW(b, filename);\r
2613         FreeBuf(b);\r
2614 \r
2615         return ret;\r
2616 }\r
2617 \r
2618 // K を BUF に変換する\r
2619 BUF *KToBuf(K *k, bool text, char *password)\r
2620 {\r
2621         BUF *buf;\r
2622         BIO *bio;\r
2623         // 引数チェック\r
2624         if (k == NULL)\r
2625         {\r
2626                 return NULL;\r
2627         }\r
2628 \r
2629         bio = KToBio(k, text, password);\r
2630         if (bio == NULL)\r
2631         {\r
2632                 return NULL;\r
2633         }\r
2634 \r
2635         buf = BioToBuf(bio);\r
2636         FreeBio(bio);\r
2637 \r
2638         SeekBuf(buf, 0, 0);\r
2639 \r
2640         return buf;\r
2641 }\r
2642 \r
2643 // K を BIO に変換する\r
2644 BIO *KToBio(K *k, bool text, char *password)\r
2645 {\r
2646         BIO *bio;\r
2647         // 引数チェック\r
2648         if (k == NULL)\r
2649         {\r
2650                 return NULL;\r
2651         }\r
2652 \r
2653         bio = NewBio();\r
2654 \r
2655         if (k->private_key)\r
2656         {\r
2657                 // 秘密鍵\r
2658                 if (text == false)\r
2659                 {\r
2660                         // バイナリ形式\r
2661                         Lock(openssl_lock);\r
2662                         {\r
2663                                 i2d_PrivateKey_bio(bio, k->pkey);\r
2664                         }\r
2665                         Unlock(openssl_lock);\r
2666                 }\r
2667                 else\r
2668                 {\r
2669                         // テキスト形式\r
2670                         if (password == 0 || StrLen(password) == 0)\r
2671                         {\r
2672                                 // 暗号化無し\r
2673                                 Lock(openssl_lock);\r
2674                                 {\r
2675                                         PEM_write_bio_PrivateKey(bio, k->pkey, NULL, NULL, 0, NULL, NULL);\r
2676                                 }\r
2677                                 Unlock(openssl_lock);\r
2678                         }\r
2679                         else\r
2680                         {\r
2681                                 // 暗号化する\r
2682                                 CB_PARAM cb;\r
2683                                 cb.password = password;\r
2684                                 Lock(openssl_lock);\r
2685                                 {\r
2686                                         PEM_write_bio_PrivateKey(bio, k->pkey, EVP_des_ede3_cbc(),\r
2687                                                 NULL, 0, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);\r
2688                                 }\r
2689                                 Unlock(openssl_lock);\r
2690                         }\r
2691                 }\r
2692         }\r
2693         else\r
2694         {\r
2695                 // 公開鍵\r
2696                 if (text == false)\r
2697                 {\r
2698                         // バイナリ形式\r
2699                         Lock(openssl_lock);\r
2700                         {\r
2701                                 i2d_PUBKEY_bio(bio, k->pkey);\r
2702                         }\r
2703                         Unlock(openssl_lock);\r
2704                 }\r
2705                 else\r
2706                 {\r
2707                         // テキスト形式\r
2708                         Lock(openssl_lock);\r
2709                         {\r
2710                                 PEM_write_bio_PUBKEY(bio, k->pkey);\r
2711                         }\r
2712                         Unlock(openssl_lock);\r
2713                 }\r
2714         }\r
2715 \r
2716         return bio;\r
2717 }\r
2718 \r
2719 // BUF が Base64 エンコードされているかどうか調べる\r
2720 bool IsBase64(BUF *b)\r
2721 {\r
2722         UINT i;\r
2723         // 引数チェック\r
2724         if (b == NULL)\r
2725         {\r
2726                 return false;\r
2727         }\r
2728 \r
2729         for (i = 0;i < b->Size;i++)\r
2730         {\r
2731                 char c = ((char *)b->Buf)[i];\r
2732                 bool b = false;\r
2733                 if ('a' <= c && c <= 'z')\r
2734                 {\r
2735                         b = true;\r
2736                 }\r
2737                 else if ('A' <= c && c <= 'Z')\r
2738                 {\r
2739                         b = true;\r
2740                 }\r
2741                 else if ('0' <= c && c <= '9')\r
2742                 {\r
2743                         b = true;\r
2744                 }\r
2745                 else if (c == ':' || c == '.' || c == ';' || c == ',')\r
2746                 {\r
2747                         b = true;\r
2748                 }\r
2749                 else if (c == '!' || c == '&' || c == '#' || c == '(' || c == ')')\r
2750                 {\r
2751                         b = true;\r
2752                 }\r
2753                 else if (c == '-' || c == ' ')\r
2754                 {\r
2755                         b = true;\r
2756                 }\r
2757                 else if (c == 13 || c == 10 || c == EOF)\r
2758                 {\r
2759                         b = true;\r
2760                 }\r
2761                 else if (c == '\t' || c == '=' || c == '+' || c == '/')\r
2762                 {\r
2763                         b = true;\r
2764                 }\r
2765                 if (b == false)\r
2766                 {\r
2767                         return false;\r
2768                 }\r
2769         }\r
2770         return true;\r
2771 }\r
2772 \r
2773 // BUF に含まれている K が暗号化されているかどうか調べる\r
2774 bool IsEncryptedK(BUF *b, bool private_key)\r
2775 {\r
2776         K *k;\r
2777         // 引数チェック\r
2778         if (b == NULL)\r
2779         {\r
2780                 return false;\r
2781         }\r
2782         if (IsBase64(b) == false)\r
2783         {\r
2784                 return false;\r
2785         }\r
2786 \r
2787         k = BufToK(b, private_key, true, NULL);\r
2788         if (k != NULL)\r
2789         {\r
2790                 FreeK(k);\r
2791                 return false;\r
2792         }\r
2793 \r
2794         return true;\r
2795 }\r
2796 \r
2797 // BUF を K に変換\r
2798 K *BufToK(BUF *b, bool private_key, bool text, char *password)\r
2799 {\r
2800         BIO *bio;\r
2801         K *k;\r
2802         // 引数チェック\r
2803         if (b == NULL)\r
2804         {\r
2805                 return NULL;\r
2806         }\r
2807 \r
2808         bio = BufToBio(b);\r
2809         k = BioToK(bio, private_key, text, password);\r
2810         FreeBio(bio);\r
2811 \r
2812         return k;\r
2813 }\r
2814 \r
2815 // K を解放\r
2816 void FreeK(K *k)\r
2817 {\r
2818         // 引数チェック\r
2819         if (k == NULL)\r
2820         {\r
2821                 return;\r
2822         }\r
2823 \r
2824         FreePKey(k->pkey);\r
2825         Free(k);\r
2826 }\r
2827 \r
2828 // 秘密鍵を解放\r
2829 void FreePKey(EVP_PKEY *pkey)\r
2830 {\r
2831         // 引数チェック\r
2832         if (pkey == NULL)\r
2833         {\r
2834                 return;\r
2835         }\r
2836 \r
2837         EVP_PKEY_free(pkey);\r
2838 }\r
2839 \r
2840 // BIO を K に変換する\r
2841 K *BioToK(BIO *bio, bool private_key, bool text, char *password)\r
2842 {\r
2843         EVP_PKEY *pkey;\r
2844         K *k;\r
2845         // 引数チェック\r
2846         if (bio == NULL)\r
2847         {\r
2848                 return NULL;\r
2849         }\r
2850 \r
2851         if (password != NULL && StrLen(password) == 0)\r
2852         {\r
2853                 password = NULL;\r
2854         }\r
2855 \r
2856         if (private_key == false)\r
2857         {\r
2858                 // 公開鍵\r
2859                 if (text == false)\r
2860                 {\r
2861                         // バイナリ形式\r
2862                         pkey = d2i_PUBKEY_bio(bio, NULL);\r
2863                         if (pkey == NULL)\r
2864                         {\r
2865                                 return NULL;\r
2866                         }\r
2867                 }\r
2868                 else\r
2869                 {\r
2870                         // テキスト形式\r
2871                         CB_PARAM cb;\r
2872                         cb.password = password;\r
2873                         Lock(openssl_lock);\r
2874                         {\r
2875                                 pkey = PEM_read_bio_PUBKEY(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);\r
2876                         }\r
2877                         Unlock(openssl_lock);\r
2878                         if (pkey == NULL)\r
2879                         {\r
2880                                 return NULL;\r
2881                         }\r
2882                 }\r
2883         }\r
2884         else\r
2885         {\r
2886                 if (text == false)\r
2887                 {\r
2888                         // バイナリ形式\r
2889                         Lock(openssl_lock);\r
2890                         {\r
2891                                 pkey = d2i_PrivateKey_bio(bio, NULL);\r
2892                         }\r
2893                         Unlock(openssl_lock);\r
2894                         if (pkey == NULL)\r
2895                         {\r
2896                                 return NULL;\r
2897                         }\r
2898                 }\r
2899                 else\r
2900                 {\r
2901                         // テキスト形式\r
2902                         CB_PARAM cb;\r
2903                         cb.password = password;\r
2904                         Lock(openssl_lock);\r
2905                         {\r
2906                                 pkey = PEM_read_bio_PrivateKey(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);\r
2907                         }\r
2908                         Unlock(openssl_lock);\r
2909                         if (pkey == NULL)\r
2910                         {\r
2911                                 return NULL;\r
2912                         }\r
2913                 }\r
2914         }\r
2915 \r
2916         k = ZeroMalloc(sizeof(K));\r
2917         k->pkey = pkey;\r
2918         k->private_key = private_key;\r
2919 \r
2920         return k;\r
2921 }\r
2922 \r
2923 // パスワードコールバック関数\r
2924 int PKeyPasswordCallbackFunction(char *buf, int bufsize, int verify, void *param)\r
2925 {\r
2926         CB_PARAM *cb;\r
2927         // 引数チェック\r
2928         if (buf == NULL || param == NULL || bufsize == 0)\r
2929         {\r
2930                 return 0;\r
2931         }\r
2932 \r
2933         cb = (CB_PARAM *)param;\r
2934         if (cb->password == NULL)\r
2935         {\r
2936                 return 0;\r
2937         }\r
2938 \r
2939         return StrCpy(buf, bufsize, cb->password);\r
2940 }\r
2941 \r
2942 // X を BUF に変換する\r
2943 BUF *XToBuf(X *x, bool text)\r
2944 {\r
2945         BIO *bio;\r
2946         BUF *b;\r
2947         // 引数チェック\r
2948         if (x == NULL)\r
2949         {\r
2950                 return NULL;\r
2951         }\r
2952 \r
2953         bio = XToBio(x, text);\r
2954         if (bio == NULL)\r
2955         {\r
2956                 return NULL;\r
2957         }\r
2958 \r
2959         b = BioToBuf(bio);\r
2960         FreeBio(bio);\r
2961 \r
2962         SeekBuf(b, 0, 0);\r
2963 \r
2964         return b;\r
2965 }\r
2966 \r
2967 // X を BIO に変換する\r
2968 BIO *XToBio(X *x, bool text)\r
2969 {\r
2970         BIO *bio;\r
2971         // 引数チェック\r
2972         if (x == NULL)\r
2973         {\r
2974                 return NULL;\r
2975         }\r
2976 \r
2977         bio = NewBio();\r
2978 \r
2979         Lock(openssl_lock);\r
2980         {\r
2981                 if (text == false)\r
2982                 {\r
2983                         // バイナリ形式\r
2984                         i2d_X509_bio(bio, x->x509);\r
2985                 }\r
2986                 else\r
2987                 {\r
2988                         // テキスト形式\r
2989                         PEM_write_bio_X509(bio, x->x509);\r
2990                 }\r
2991         }\r
2992         Unlock(openssl_lock);\r
2993 \r
2994         return bio;\r
2995 }\r
2996 \r
2997 // X の解放\r
2998 void FreeX(X *x)\r
2999 {\r
3000         // 引数チェック\r
3001         if (x == NULL)\r
3002         {\r
3003                 return;\r
3004         }\r
3005 \r
3006         // 名前解放\r
3007         FreeXNames(x);\r
3008 \r
3009 \r
3010         // シリアル解放\r
3011         FreeXSerial(x->serial);\r
3012 \r
3013         if (x->do_not_free == false)\r
3014         {\r
3015                 FreeX509(x->x509);\r
3016         }\r
3017         Free(x);\r
3018 }\r
3019 \r
3020 // X509 の解放\r
3021 void FreeX509(X509 *x509)\r
3022 {\r
3023         // 引数チェック\r
3024         if (x509 == NULL)\r
3025         {\r
3026                 return;\r
3027         }\r
3028 \r
3029         Lock(openssl_lock);\r
3030         {\r
3031                 X509_free(x509);\r
3032         }\r
3033         Unlock(openssl_lock);\r
3034 }\r
3035 \r
3036 // BUF を X に変換する\r
3037 X *BufToX(BUF *b, bool text)\r
3038 {\r
3039         X *x;\r
3040         BIO *bio;\r
3041         // 引数チェック\r
3042         if (b == NULL)\r
3043         {\r
3044                 return NULL;\r
3045         }\r
3046 \r
3047         bio = BufToBio(b);\r
3048         if (bio == NULL)\r
3049         {\r
3050                 return NULL;\r
3051         }\r
3052 \r
3053         x = BioToX(bio, text);\r
3054 \r
3055         FreeBio(bio);\r
3056 \r
3057         return x;\r
3058 }\r
3059 \r
3060 // X のダイジェストを取得する\r
3061 void GetXDigest(X *x, UCHAR *buf, bool sha1)\r
3062 {\r
3063         // 引数チェック\r
3064         if (x == NULL)\r
3065         {\r
3066                 return;\r
3067         }\r
3068 \r
3069         if (sha1 == false)\r
3070         {\r
3071                 UINT size = MD5_SIZE;\r
3072                 X509_digest(x->x509, EVP_md5(), buf, (unsigned int *)&size);\r
3073         }\r
3074         else\r
3075         {\r
3076                 UINT size = SHA1_SIZE;\r
3077                 X509_digest(x->x509, EVP_sha1(), buf, (unsigned int *)&size);\r
3078         }\r
3079 }\r
3080 \r
3081 // BIO を X に変換する\r
3082 X *BioToX(BIO *bio, bool text)\r
3083 {\r
3084         X *x;\r
3085         X509 *x509;\r
3086         // 引数チェック\r
3087         if (bio == NULL)\r
3088         {\r
3089                 return NULL;\r
3090         }\r
3091 \r
3092         Lock(openssl_lock);\r
3093         {\r
3094                 // x509 の読み込み\r
3095                 if (text == false)\r
3096                 {\r
3097                         // バイナリモード\r
3098                         x509 = d2i_X509_bio(bio, NULL);\r
3099                 }\r
3100                 else\r
3101                 {\r
3102                         // テキストモード\r
3103                         x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);\r
3104                 }\r
3105         }\r
3106         Unlock(openssl_lock);\r
3107 \r
3108         if (x509 == NULL)\r
3109         {\r
3110                 return NULL;\r
3111         }\r
3112 \r
3113         x = X509ToX(x509);\r
3114 \r
3115         if (x == NULL)\r
3116         {\r
3117                 return NULL;\r
3118         }\r
3119 \r
3120         return x;\r
3121 }\r
3122 \r
3123 // X509 を X に変換する\r
3124 X *X509ToX(X509 *x509)\r
3125 {\r
3126         X *x;\r
3127         K *k;\r
3128         BUF *b;\r
3129         UINT size;\r
3130         UINT type;\r
3131         // 引数チェック\r
3132         if (x509 == NULL)\r
3133         {\r
3134                 return NULL;\r
3135         }\r
3136 \r
3137         x = ZeroMalloc(sizeof(X));\r
3138         x->x509 = x509;\r
3139 \r
3140         // 名前\r
3141         LoadXNames(x);\r
3142 \r
3143         // 有効期限\r
3144         LoadXDates(x);\r
3145 \r
3146         // ルート証明書かどうかチェックする\r
3147         if (CompareName(x->issuer_name, x->subject_name))\r
3148         {\r
3149                 K *pubkey = GetKFromX(x);\r
3150                 if (pubkey != NULL)\r
3151                 {\r
3152                         if (CheckXandK(x, pubkey))\r
3153                         {\r
3154                                 x->root_cert = true;\r
3155                         }\r
3156                         FreeK(pubkey);\r
3157                 }\r
3158         }\r
3159 \r
3160         // シリアル番号の取得\r
3161         x->serial = NewXSerial(x509->cert_info->serialNumber->data,\r
3162                 x509->cert_info->serialNumber->length);\r
3163         if (x->serial == NULL)\r
3164         {\r
3165                 char zero = 0;\r
3166                 x->serial = NewXSerial(&zero, sizeof(char));\r
3167         }\r
3168 \r
3169         k = GetKFromX(x);\r
3170         if (k == NULL)\r
3171         {\r
3172                 FreeX(x);\r
3173                 return NULL;\r
3174         }\r
3175 \r
3176         b = KToBuf(k, false, NULL);\r
3177 \r
3178         size = b->Size;\r
3179         type = k->pkey->type;\r
3180 \r
3181         FreeBuf(b);\r
3182 \r
3183         FreeK(k);\r
3184 \r
3185         if (type == EVP_PKEY_RSA)\r
3186         {\r
3187                 x->is_compatible_bit = true;\r
3188 \r
3189                 switch (size)\r
3190                 {\r
3191                 case 162:\r
3192                         x->bits = 1024;\r
3193                         break;\r
3194 \r
3195                 case 226:\r
3196                         x->bits = 1536;\r
3197                         break;\r
3198 \r
3199                 case 294:\r
3200                         x->bits = 2048;\r
3201                         break;\r
3202 \r
3203                 case 442:\r
3204                         x->bits = 3072;\r
3205                         break;\r
3206 \r
3207                 case 550:\r
3208                         x->bits = 4096;\r
3209                         break;\r
3210 \r
3211                 default:\r
3212                         x->is_compatible_bit = false;\r
3213                         break;\r
3214                 }\r
3215         }\r
3216 \r
3217         return x;\r
3218 }\r
3219 \r
3220 // BIO を作成する\r
3221 BIO *NewBio()\r
3222 {\r
3223         return BIO_new(BIO_s_mem());\r
3224 }\r
3225 \r
3226 // BIO を解放する\r
3227 void FreeBio(BIO *bio)\r
3228 {\r
3229         // 引数チェック\r
3230         if (bio == NULL)\r
3231         {\r
3232                 return;\r
3233         }\r
3234 \r
3235         BIO_free(bio);\r
3236 }\r
3237 \r
3238 // BIO を BUF に変換する\r
3239 BUF *BioToBuf(BIO *bio)\r
3240 {\r
3241         BUF *b;\r
3242         UINT size;\r
3243         void *tmp;\r
3244         // 引数チェック\r
3245         if (bio == NULL)\r
3246         {\r
3247                 return NULL;\r
3248         }\r
3249 \r
3250         BIO_seek(bio, 0);\r
3251         size = bio->num_write;\r
3252         tmp = Malloc(size);\r
3253         BIO_read(bio, tmp, size);\r
3254 \r
3255         b = NewBuf();\r
3256         WriteBuf(b, tmp, size);\r
3257         Free(tmp);\r
3258 \r
3259         return b;\r
3260 }\r
3261 \r
3262 // BUF を BIO に変換する\r
3263 BIO *BufToBio(BUF *b)\r
3264 {\r
3265         BIO *bio;\r
3266         // 引数チェック\r
3267         if (b == NULL)\r
3268         {\r
3269                 return NULL;\r
3270         }\r
3271 \r
3272         Lock(openssl_lock);\r
3273         {\r
3274                 bio = BIO_new(BIO_s_mem());\r
3275                 if (bio == NULL)\r
3276                 {\r
3277                         Unlock(openssl_lock);\r
3278                         return NULL;\r
3279                 }\r
3280                 BIO_write(bio, b->Buf, b->Size);\r
3281                 BIO_seek(bio, 0);\r
3282         }\r
3283         Unlock(openssl_lock);\r
3284 \r
3285         return bio;\r
3286 }\r
3287 \r
3288 // 128bit 乱数生成\r
3289 void Rand128(void *buf)\r
3290 {\r
3291         Rand(buf, 16);\r
3292 }\r
3293 \r
3294 // 64bit 乱数生成\r
3295 UINT64 Rand64()\r
3296 {\r
3297         UINT64 i;\r
3298         Rand(&i, sizeof(i));\r
3299         return i;\r
3300 }\r
3301 \r
3302 // 32bit 乱数生成\r
3303 UINT Rand32()\r
3304 {\r
3305         UINT i;\r
3306         Rand(&i, sizeof(i));\r
3307         return i;\r
3308 }\r
3309 \r
3310 // 16bit 乱数生成\r
3311 USHORT Rand16()\r
3312 {\r
3313         USHORT i;\r
3314         Rand(&i, sizeof(i));\r
3315         return i;\r
3316 }\r
3317 \r
3318 // 8bit 乱数生成\r
3319 UCHAR Rand8()\r
3320 {\r
3321         UCHAR i;\r
3322         Rand(&i, sizeof(i));\r
3323         return i;\r
3324 }\r
3325 \r
3326 // 1bit 乱数生成\r
3327 bool Rand1()\r
3328 {\r
3329         return (Rand32() % 2) == 0 ? false : true;\r
3330 }\r
3331 \r
3332 // 乱数生成\r
3333 void Rand(void *buf, UINT size)\r
3334 {\r
3335         // 引数チェック\r
3336         if (buf == NULL || size == 0)\r
3337         {\r
3338                 return;\r
3339         }\r
3340         RAND_bytes(buf, size);\r
3341 }\r
3342 \r
3343 // OpenSSL が確保しているスレッド固有情報を削除する\r
3344 void FreeOpenSSLThreadState()\r
3345 {\r
3346         ERR_remove_state(0);\r
3347 }\r
3348 \r
3349 // 暗号化ライブラリの解放\r
3350 void FreeCryptLibrary()\r
3351 {\r
3352         openssl_inited = false;\r
3353 \r
3354         DeleteLock(openssl_lock);\r
3355         openssl_lock = NULL;\r
3356 //      RAND_Free_For_SoftEther();\r
3357         OpenSSL_FreeLock();\r
3358 }\r
3359 \r
3360 // 暗号化ライブラリの初期化\r
3361 void InitCryptLibrary()\r
3362 {\r
3363         char tmp[16];\r
3364 //      RAND_Init_For_SoftEther()\r
3365         openssl_lock = NewLock();\r
3366         SSL_library_init();\r
3367         //OpenSSL_add_all_algorithms();\r
3368         OpenSSL_add_all_ciphers();\r
3369         SSLeay_add_all_digests();\r
3370         ERR_load_crypto_strings();\r
3371         SSL_load_error_strings();\r
3372 \r
3373 #ifdef  OS_UNIX\r
3374         {\r
3375                 char *name1 = "/dev/random";\r
3376                 char *name2 = "/dev/urandom";\r
3377                 IO *o;\r
3378                 o = FileOpen(name1, false);\r
3379                 if (o == NULL)\r
3380                 {\r
3381                         o = FileOpen(name2, false);\r
3382                         if (o == NULL)\r
3383                         {\r
3384                                 UINT64 now = SystemTime64();\r
3385                                 BUF *b;\r
3386                                 UINT i;\r
3387                                 b = NewBuf();\r
3388                                 for (i = 0;i < 4096;i++)\r
3389                                 {\r
3390                                         UCHAR c = rand() % 256;\r
3391                                         WriteBuf(b, &c, 1);\r
3392                                 }\r
3393                                 WriteBuf(b, &now, sizeof(now));\r
3394                                 RAND_seed(b->Buf, b->Size);\r
3395                                 FreeBuf(b);\r
3396                         }\r
3397                         else\r
3398                         {\r
3399                                 FileClose(o);\r
3400                         }\r
3401                 }\r
3402                 else\r
3403                 {\r
3404                         FileClose(o);\r
3405                 }\r
3406         }\r
3407 #endif  // OS_UNIX\r
3408 \r
3409         RAND_poll();\r
3410 \r
3411 #ifdef  OS_WIN32\r
3412 //      RAND_screen();\r
3413 #endif\r
3414         Rand(tmp, sizeof(tmp));\r
3415         OpenSSL_InitLock();\r
3416 \r
3417         openssl_inited = true;\r
3418 }\r
3419 \r
3420 // 内部ハッシュ関数\r
3421 void InternalHash(void *dst, void *src, UINT size, bool sha1)\r
3422 {\r
3423         // 引数チェック\r
3424         if (dst == NULL || (src == NULL && size != 0))\r
3425         {\r
3426                 return;\r
3427         }\r
3428 \r
3429         if (sha1 == false)\r
3430         {\r
3431                 // MD5 ハッシュ\r
3432                 MD5(src, size, dst);\r
3433         }\r
3434         else\r
3435         {\r
3436                 // SHA ハッシュ\r
3437                 SHA(src, size, dst);\r
3438         }\r
3439 }\r
3440 \r
3441 // SHA-1 専用ハッシュ関数\r
3442 void HashSha1(void *dst, void *src, UINT size)\r
3443 {\r
3444         SHA1(src, size, dst);\r
3445 }\r
3446 \r
3447 // ハッシュ関数\r
3448 void Hash(void *dst, void *src, UINT size, bool sha1)\r
3449 {\r
3450         InternalHash(dst, src, size, sha1);\r
3451 }\r
3452 \r
3453 // 新しい CRYPT オブジェクトの作成\r
3454 CRYPT *NewCrypt(void *key, UINT size)\r
3455 {\r
3456         CRYPT *c = ZeroMalloc(sizeof(CRYPT));\r
3457 \r
3458         SetKey(c, key, size);\r
3459 \r
3460         return c;\r
3461 }\r
3462 \r
3463 // CRYPT オブジェクトの解放\r
3464 void FreeCrypt(CRYPT *c)\r
3465 {\r
3466         // 引数チェック\r
3467         if (c == NULL)\r
3468         {\r
3469                 return;\r
3470         }\r
3471 \r
3472         // メモリ解放\r
3473         Free(c);\r
3474 }\r
3475 \r
3476 // 暗号化と解読\r
3477 void InternalEncrypt(CRYPT *c, void *dst, void *src, UINT size)\r
3478 {\r
3479         UINT x, y, sx, sy;\r
3480         UINT *state;\r
3481         UCHAR *endsrc;\r
3482         UCHAR *s = (UCHAR *)src;\r
3483         UCHAR *d = (UCHAR *)dst;\r
3484         // 引数チェック\r
3485         if (c == NULL || dst == NULL || src == NULL || size == 0)\r
3486         {\r
3487                 return;\r
3488         }\r
3489 \r
3490         state = (UINT *)c->state;\r
3491         x = c->x;\r
3492         y = c->y;\r
3493 \r
3494         for (endsrc = s + size;s != endsrc;s++, d++)\r
3495         {\r
3496                 x = (x + 1) & 0xff;\r
3497                 sx = state[x];\r
3498                 y = (sx + y) & 0xff;\r
3499                 state[x] = sy = state[y];\r
3500                 state[y] = sx;\r
3501                 *d = *s ^ state[(sx + sy) & 0xff];\r
3502         }\r
3503         c->x = x;\r
3504         c->y = y;\r
3505 }\r
3506 void Encrypt(CRYPT *c, void *dst, void *src, UINT size)\r
3507 {\r
3508         InternalEncrypt(c, dst, src, size);\r
3509 }\r
3510 \r
3511 // 鍵の更新\r
3512 void SetKey(CRYPT *c, void *key, UINT size)\r
3513 {\r
3514         UINT i, t, u, ki, si;\r
3515         UINT *state;\r
3516         UCHAR *k = (UCHAR *)key;\r
3517         // 引数チェック\r
3518         if (c == NULL || key == NULL)\r
3519         {\r
3520                 return;\r
3521         }\r
3522 \r
3523         // 鍵のセット\r
3524         state = (UINT *)c->state;\r
3525         c->x = c->y = 0;\r
3526         for (i = 0;i < 256;i++)\r
3527         {\r
3528                 state[i] = i;\r
3529         }\r
3530         ki = si = 0;\r
3531 \r
3532         for (i = 0;i < 256;i++)\r
3533         {\r
3534                 t = state[i];\r
3535                 si = (si + k[ki] + t) & 0xff;\r
3536                 u = state[si];\r
3537                 state[si] = t;\r
3538                 state[i] = u;\r
3539                 if (++ki >= size)\r
3540                 {\r
3541                         ki = 0;\r
3542                 }\r
3543         }\r
3544 }\r
3545 \r