* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Secure.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 // Secure.c\r
79 // セキュリティトークン管理モジュール\r
80 \r
81 #define SECURE_C\r
82 #define ENCRYPT_C\r
83 \r
84 #ifdef  WIN32\r
85 #include <windows.h>\r
86 #endif  // WIN32\r
87 \r
88 #include <stdio.h>\r
89 #include <stdlib.h>\r
90 #include <string.h>\r
91 #include <wchar.h>\r
92 #include <stdarg.h>\r
93 #include <time.h>\r
94 #include <errno.h>\r
95 #include <openssl/ssl.h>\r
96 #include <openssl/err.h>\r
97 #include <openssl/rand.h>\r
98 #include <openssl/engine.h>\r
99 #include <openssl/bio.h>\r
100 #include <openssl/x509.h>\r
101 #include <openssl/pkcs7.h>\r
102 #include <openssl/pkcs12.h>\r
103 #include <openssl/rc4.h>\r
104 #include <openssl/md5.h>\r
105 #include <openssl/sha.h>\r
106 #include <Mayaqua/Mayaqua.h>\r
107 #include <Mayaqua/cryptoki.h>\r
108 \r
109 \r
110 #define MAX_OBJ                         1024            // ハードウェア内の最大オブジェクト数 (想定)\r
111 \r
112 #define A_SIZE(a, i)            (a[(i)].ulValueLen)\r
113 #define A_SET(a, i, value, size)        (a[i].pValue = value;a[i].ulValueLen = size;)\r
114 \r
115 #ifdef  OS_WIN32\r
116 // Win32 用コード\r
117 \r
118 // Win32 用 DLL 読み込み\r
119 HINSTANCE Win32SecureLoadLibraryEx(char *dllname, DWORD flags)\r
120 {\r
121         char tmp1[MAX_PATH];\r
122         char tmp2[MAX_PATH];\r
123         char tmp3[MAX_PATH];\r
124         HINSTANCE h;\r
125         // 引数チェック\r
126         if (dllname == NULL)\r
127         {\r
128                 return NULL;\r
129         }\r
130 \r
131         Format(tmp1, sizeof(tmp1), "%s\\%s", MsGetSystem32Dir(), dllname);\r
132         Format(tmp2, sizeof(tmp2), "%s\\JPKI\\%s", MsGetProgramFilesDir(), dllname);\r
133         Format(tmp3, sizeof(tmp3), "%s\\LGWAN\\%s", MsGetProgramFilesDir(), dllname);\r
134 \r
135         h = LoadLibraryEx(dllname, NULL, flags);\r
136         if (h != NULL)\r
137         {\r
138                 return h;\r
139         }\r
140 \r
141         h = LoadLibraryEx(tmp1, NULL, flags);\r
142         if (h != NULL)\r
143         {\r
144                 return h;\r
145         }\r
146 \r
147         h = LoadLibraryEx(tmp2, NULL, flags);\r
148         if (h != NULL)\r
149         {\r
150                 return h;\r
151         }\r
152 \r
153         h = LoadLibraryEx(tmp3, NULL, flags);\r
154         if (h != NULL)\r
155         {\r
156                 return h;\r
157         }\r
158 \r
159         return NULL;\r
160 }\r
161 \r
162 // 指定したデバイスがインストールされているか調査\r
163 bool Win32IsDeviceSupported(SECURE_DEVICE *dev)\r
164 {\r
165         HINSTANCE hInst;\r
166         // 引数チェック\r
167         if (dev == NULL)\r
168         {\r
169                 return false;\r
170         }\r
171 \r
172         // DLL が読み込み可能かチェック\r
173         hInst = Win32SecureLoadLibraryEx(dev->ModuleName, DONT_RESOLVE_DLL_REFERENCES);\r
174         if (hInst == NULL)\r
175         {\r
176                 return false;\r
177         }\r
178 \r
179         FreeLibrary(hInst);\r
180 \r
181         return true;\r
182 }\r
183 \r
184 // デバイスモジュールの読み込み\r
185 bool Win32LoadSecModule(SECURE *sec)\r
186 {\r
187         SEC_DATA_WIN32 *w;\r
188         HINSTANCE hInst;\r
189         CK_FUNCTION_LIST_PTR api = NULL;\r
190         CK_RV (*get_function_list)(CK_FUNCTION_LIST_PTR_PTR);\r
191         // 引数チェック\r
192         if (sec == NULL)\r
193         {\r
194                 return false;\r
195         }\r
196 \r
197         if (sec->Dev->Id == 9)\r
198         {\r
199                 char username[MAX_SIZE];\r
200                 DWORD size;\r
201                 // 住基ネットのデバイスドライバでは、Software\JPKI レジストリキーの内容を\r
202                 // SYSTEM の HKLU でも持っていなければならないので、もし持っていない場合は\r
203                 // 別のユーザーの値からコピーする\r
204 //              if (MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "Name") == false ||\r
205 //                      MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "RWType") == false)\r
206                 size = sizeof(username);\r
207                 GetUserName(username, &size);\r
208                 if (StrCmpi(username, "System") == 0)\r
209                 {\r
210                         TOKEN_LIST *t = MsRegEnumKey(REG_USERS, NULL);\r
211 \r
212                         if (t != NULL)\r
213                         {\r
214                                 UINT i;\r
215 \r
216                                 for (i = 0;i < t->NumTokens;i++)\r
217                                 {\r
218                                         char tmp[MAX_PATH];\r
219 \r
220                                         if (StrCmpi(t->Token[i], ".DEFAULT") != 0 && StrCmpi(t->Token[i], "S-1-5-18") != 0)\r
221                                         {\r
222                                                 Format(tmp, sizeof(tmp), "%s\\Software\\JPKI", t->Token[i]);\r
223 \r
224                                                 if (MsRegIsValue(REG_USERS, tmp, "Name") && MsRegIsValue(REG_USERS, tmp, "RWType"))\r
225                                                 {\r
226                                                         char *name = MsRegReadStr(REG_USERS, tmp, "Name");\r
227                                                         char *port = MsRegReadStr(REG_USERS, tmp, "Port");\r
228                                                         UINT type = MsRegReadInt(REG_USERS, tmp, "RWType");\r
229 \r
230                                                         MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Name", name);\r
231                                                         MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Port", port);\r
232                                                         MsRegWriteInt(REG_CURRENT_USER, "Software\\JPKI", "RWType", type);\r
233 \r
234                                                         Free(name);\r
235                                                         Free(port);\r
236                                                         break;\r
237                                                 }\r
238                                         }\r
239                                 }\r
240 \r
241                                 FreeToken(t);\r
242                         }\r
243                 }\r
244         }\r
245 \r
246         // ライブラリのロード\r
247         hInst = Win32SecureLoadLibraryEx(sec->Dev->ModuleName, 0);\r
248         if (hInst == NULL)\r
249         {\r
250                 // 失敗\r
251                 return false;\r
252         }\r
253 \r
254         // API の取得\r
255         get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))\r
256                 GetProcAddress(hInst, "C_GetFunctionList");\r
257 \r
258         if (get_function_list == NULL)\r
259         {\r
260                 // 失敗\r
261                 FreeLibrary(hInst);\r
262                 return false;\r
263         }\r
264 \r
265         get_function_list(&api);\r
266         if (api == NULL)\r
267         {\r
268                 // 失敗\r
269                 FreeLibrary(hInst);\r
270                 return false;\r
271         }\r
272 \r
273         sec->Data = ZeroMalloc(sizeof(SEC_DATA_WIN32));\r
274         w = sec->Data;\r
275 \r
276         w->hInst = hInst;\r
277         sec->Api = api;\r
278 \r
279         return true;\r
280 }\r
281 \r
282 // デバイスモジュールのアンロード\r
283 void Win32FreeSecModule(SECURE *sec)\r
284 {\r
285         // 引数チェック\r
286         if (sec == NULL)\r
287         {\r
288                 return;\r
289         }\r
290         if (sec->Data == NULL)\r
291         {\r
292                 return;\r
293         }\r
294 \r
295         // アンロード\r
296         FreeLibrary(sec->Data->hInst);\r
297         Free(sec->Data);\r
298 \r
299         sec->Data = NULL;\r
300 }\r
301 \r
302 #endif  // OS_WIN32\r
303 \r
304 \r
305 // 指定されたデバイスが JPKI かどうか\r
306 bool IsJPKI(bool id)\r
307 {\r
308         if (id == 9 || id == 13)\r
309         {\r
310                 return true;\r
311         }\r
312 \r
313         return false;\r
314 }\r
315 \r
316 // セキュアデバイスの秘密鍵を名前を指定して署名\r
317 bool SignSec(SECURE *sec, char *name, void *dst, void *src, UINT size)\r
318 {\r
319         SEC_OBJ *obj;\r
320         UINT ret;\r
321         // 引数チェック\r
322         if (sec == NULL)\r
323         {\r
324                 return false;\r
325         }\r
326         if (name == NULL || dst == NULL || src == NULL)\r
327         {\r
328                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
329                 return false;\r
330         }\r
331 \r
332         obj = FindSecObject(sec, name, SEC_K);\r
333         if (obj == NULL)\r
334         {\r
335                 return false;\r
336         }\r
337 \r
338         ret = SignSecByObject(sec, obj, dst, src, size);\r
339 \r
340         FreeSecObject(obj);\r
341 \r
342         return ret;\r
343 }\r
344 \r
345 // セキュアデバイスの秘密鍵で署名\r
346 bool SignSecByObject(SECURE *sec, SEC_OBJ *obj, void *dst, void *src, UINT size)\r
347 {\r
348         CK_MECHANISM mechanism = {CKM_RSA_PKCS, NULL, 0};\r
349         UINT ret;\r
350         UCHAR hash[SIGN_HASH_SIZE];\r
351         // 引数チェック\r
352         if (sec == NULL)\r
353         {\r
354                 return false;\r
355         }\r
356         if (obj == NULL || dst == NULL || src == NULL)\r
357         {\r
358                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
359                 return false;\r
360         }\r
361         if (sec->SessionCreated == false)\r
362         {\r
363                 sec->Error = SEC_ERROR_NO_SESSION;\r
364                 return false;\r
365         }\r
366         if (sec->LoginFlag == false && obj->Private)\r
367         {\r
368                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
369                 return false;\r
370         }\r
371         if (obj->Type != SEC_K)\r
372         {\r
373                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
374                 return false;\r
375         }\r
376 \r
377         // ハッシュ\r
378         HashForSign(hash, sizeof(hash), src, size);\r
379 \r
380         // 署名初期化\r
381         ret = sec->Api->C_SignInit(sec->SessionId, &mechanism, obj->Object);\r
382         if (ret != CKR_OK)\r
383         {\r
384                 // 失敗\r
385                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
386                 Debug("C_SignInit Error: 0x%x\n", ret);\r
387                 return false;\r
388         }\r
389 \r
390         // 署名実行\r
391         size = 128;\r
392         ret = sec->Api->C_Sign(sec->SessionId, hash, sizeof(hash), dst, &size);\r
393         if (ret != CKR_OK || size != 128)\r
394         {\r
395                 // 失敗\r
396                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
397                 Debug("C_Sign Error: 0x%x\n", ret);\r
398                 return false;\r
399         }\r
400 \r
401         return true;\r
402 }\r
403 \r
404 // PIN コードの変更\r
405 bool ChangePin(SECURE *sec, char *old_pin, char *new_pin)\r
406 {\r
407         // 引数チェック\r
408         if (sec == NULL || old_pin == NULL || new_pin == NULL)\r
409         {\r
410                 return false;\r
411         }\r
412         if (sec->SessionCreated == false)\r
413         {\r
414                 sec->Error = SEC_ERROR_NO_SESSION;\r
415                 return false;\r
416         }\r
417         if (sec->LoginFlag == false)\r
418         {\r
419                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
420                 return false;\r
421         }\r
422         if (sec->IsReadOnly)\r
423         {\r
424                 sec->Error = SEC_ERROR_OPEN_SESSION;\r
425                 return false;\r
426         }\r
427 \r
428         // PIN 変更\r
429         if (sec->Api->C_SetPIN(sec->SessionId, old_pin, StrLen(old_pin),\r
430                 new_pin, StrLen(new_pin)) != CKR_OK)\r
431         {\r
432                 return false;\r
433         }\r
434 \r
435         return true;\r
436 }\r
437 \r
438 // 秘密鍵オブジェクトの書き込み\r
439 bool WriteSecKey(SECURE *sec, bool private_obj, char *name, K *k)\r
440 {\r
441         UINT key_type = CKK_RSA;\r
442         CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;\r
443         UINT obj_class = CKO_PRIVATE_KEY;\r
444         UINT object;\r
445         UINT ret;\r
446         BUF *b;\r
447         RSA *rsa;\r
448         UCHAR modules[MAX_SIZE], pub[MAX_SIZE], pri[MAX_SIZE], prime1[MAX_SIZE], prime2[MAX_SIZE];\r
449         CK_ATTRIBUTE a[] =\r
450         {\r
451                 {CKA_MODULUS,                   modules,                0},             // 0\r
452                 {CKA_PUBLIC_EXPONENT,   pub,                    0},             // 1\r
453                 {CKA_PRIVATE_EXPONENT,  pri,                    0},             // 2\r
454                 {CKA_PRIME_1,                   prime1,                 0},             // 3\r
455                 {CKA_PRIME_2,                   prime2,                 0},             // 4\r
456                 {CKA_CLASS,                             &obj_class,             sizeof(obj_class)},\r
457                 {CKA_TOKEN,                             &b_true,                sizeof(b_true)},\r
458                 {CKA_PRIVATE,                   &b_private_obj, sizeof(b_private_obj)},\r
459                 {CKA_LABEL,                             name,                   StrLen(name)},\r
460                 {CKA_KEY_TYPE,                  &key_type,              sizeof(key_type)},\r
461                 {CKA_DERIVE,                    &b_false,               sizeof(b_false)},\r
462                 {CKA_SUBJECT,                   name,                   StrLen(name)},\r
463                 {CKA_SENSITIVE,                 &b_true,                sizeof(b_true)},\r
464                 {CKA_DECRYPT,                   &b_true,                sizeof(b_true)},\r
465                 {CKA_SIGN,                              &b_true,                sizeof(b_true)},\r
466                 {CKA_SIGN_RECOVER,              &b_false,               sizeof(b_false)},\r
467                 {CKA_EXTRACTABLE,               &b_false,               sizeof(b_false)},\r
468                 {CKA_MODIFIABLE,                &b_false,               sizeof(b_false)},\r
469         };\r
470         // 引数チェック\r
471         if (sec == NULL)\r
472         {\r
473                 return false;\r
474         }\r
475         if (name == NULL || k == NULL || k->private_key == false)\r
476         {\r
477                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
478                 return false;\r
479         }\r
480         if (sec->SessionCreated == false)\r
481         {\r
482                 sec->Error = SEC_ERROR_NO_SESSION;\r
483                 return false;\r
484         }\r
485         if (sec->LoginFlag == false && private_obj)\r
486         {\r
487                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
488                 return false;\r
489         }\r
490 \r
491         // 数値データ生成\r
492         rsa = k->pkey->pkey.rsa;\r
493         if (rsa == NULL)\r
494         {\r
495                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
496                 return false;\r
497         }\r
498         b = BigNumToBuf(rsa->n);\r
499         ReadBuf(b, modules, sizeof(modules));\r
500         A_SIZE(a, 0) = b->Size;\r
501         FreeBuf(b);\r
502 \r
503         b = BigNumToBuf(rsa->e);\r
504         ReadBuf(b, pub, sizeof(pub));\r
505         A_SIZE(a, 1) = b->Size;\r
506         FreeBuf(b);\r
507 \r
508         b = BigNumToBuf(rsa->d);\r
509         ReadBuf(b, pri, sizeof(pri));\r
510         A_SIZE(a, 2) = b->Size;\r
511         FreeBuf(b);\r
512 \r
513         b = BigNumToBuf(rsa->p);\r
514         ReadBuf(b, prime1, sizeof(prime1));\r
515         A_SIZE(a, 3) = b->Size;\r
516         FreeBuf(b);\r
517 \r
518         b = BigNumToBuf(rsa->q);\r
519         ReadBuf(b, prime2, sizeof(prime2));\r
520         A_SIZE(a, 4) = b->Size;\r
521         FreeBuf(b);\r
522 \r
523         // 古い鍵があれば削除\r
524         if (CheckSecObject(sec, name, SEC_K))\r
525         {\r
526                 DeleteSecKey(sec, name);\r
527         }\r
528 \r
529         // 作成\r
530         if ((ret = sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object)) != CKR_OK)\r
531         {\r
532                 // 失敗\r
533                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
534                 Debug("ret: 0x%x\n", ret);\r
535                 return false;\r
536         }\r
537 \r
538         // キャッシュ消去\r
539         EraseEnumSecObjectCache(sec);\r
540 \r
541         return true;\r
542 }\r
543 \r
544 // 証明書オブジェクトを名前を指定して読み込み\r
545 X *ReadSecCert(SECURE *sec, char *name)\r
546 {\r
547         SEC_OBJ *obj;\r
548         X *x;\r
549         // 引数チェック\r
550         if (sec == NULL)\r
551         {\r
552                 return false;\r
553         }\r
554         if (sec->SessionCreated == false)\r
555         {\r
556                 sec->Error = SEC_ERROR_NO_SESSION;\r
557                 return false;\r
558         }\r
559 \r
560         // 検索\r
561         obj = FindSecObject(sec, name, SEC_X);\r
562         if (obj == NULL)\r
563         {\r
564                 return false;\r
565         }\r
566 \r
567         // 取得\r
568         x = ReadSecCertFromObject(sec, obj);\r
569 \r
570         FreeSecObject(obj);\r
571 \r
572         return x;\r
573 }\r
574 \r
575 // 証明書オブジェクトの読み込み\r
576 X *ReadSecCertFromObject(SECURE *sec, SEC_OBJ *obj)\r
577 {\r
578         UINT size;\r
579         X *x;\r
580         UCHAR value[4096];\r
581         BUF *b;\r
582         CK_ATTRIBUTE get[] =\r
583         {\r
584                 {CKA_VALUE,             value,          sizeof(value)},\r
585         };\r
586         // 引数チェック\r
587         if (sec == NULL)\r
588         {\r
589                 return false;\r
590         }\r
591         if (sec->SessionCreated == false)\r
592         {\r
593                 sec->Error = SEC_ERROR_NO_SESSION;\r
594                 return false;\r
595         }\r
596         if (sec->LoginFlag == false && obj->Private)\r
597         {\r
598                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
599                 return false;\r
600         }\r
601         if (obj->Type != SEC_X)\r
602         {\r
603                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
604                 return false;\r
605         }\r
606 \r
607         // 取得\r
608         if (sec->Api->C_GetAttributeValue(\r
609                 sec->SessionId, obj->Object, get, sizeof(get) / sizeof(get[0])) != CKR_OK)\r
610         {\r
611                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
612                 return 0;\r
613         }\r
614 \r
615         size = A_SIZE(get, 0);\r
616 \r
617         // 変換\r
618         b = NewBuf();\r
619         WriteBuf(b, value, size);\r
620         SeekBuf(b, 0, 0);\r
621 \r
622         x = BufToX(b, false);\r
623         if (x == NULL)\r
624         {\r
625                 sec->Error = SEC_ERROR_INVALID_CERT;\r
626         }\r
627 \r
628         FreeBuf(b);\r
629 \r
630         return x;\r
631 }\r
632 \r
633 // 証明書オブジェクトの書き込み\r
634 bool WriteSecCert(SECURE *sec, bool private_obj, char *name, X *x)\r
635 {\r
636         UINT obj_class = CKO_CERTIFICATE;\r
637         CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;\r
638         UINT cert_type = CKC_X_509;\r
639         CK_DATE start_date, end_date;\r
640         UCHAR subject[MAX_SIZE];\r
641         UCHAR issuer[MAX_SIZE];\r
642         wchar_t w_subject[MAX_SIZE];\r
643         wchar_t w_issuer[MAX_SIZE];\r
644         UCHAR serial_number[MAX_SIZE];\r
645         UCHAR value[4096];\r
646         UINT ret;\r
647         BUF *b;\r
648         UINT object;\r
649         CK_ATTRIBUTE a[] =\r
650         {\r
651                 {CKA_SUBJECT,                   subject,                0},                     // 0\r
652                 {CKA_ISSUER,                    issuer,                 0},                     // 1\r
653                 {CKA_SERIAL_NUMBER,             serial_number,  0},                     // 2\r
654                 {CKA_VALUE,                             value,                  0},                     // 3\r
655                 {CKA_CLASS,                             &obj_class,             sizeof(obj_class)},\r
656                 {CKA_TOKEN,                             &b_true,                sizeof(b_true)},\r
657                 {CKA_PRIVATE,                   &b_private_obj, sizeof(b_private_obj)},\r
658                 {CKA_LABEL,                             name,                   StrLen(name)},\r
659                 {CKA_CERTIFICATE_TYPE,  &cert_type,             sizeof(cert_type)},\r
660 #if     0               // 失敗するトークンがあるのでこれは使わない\r
661                 {CKA_START_DATE,                &start_date,    sizeof(start_date)},\r
662                 {CKA_END_DATE,                  &end_date,              sizeof(end_date)},\r
663 #endif\r
664         };\r
665         // 引数チェック\r
666         if (sec == NULL)\r
667         {\r
668                 return false;\r
669         }\r
670         if (name == NULL)\r
671         {\r
672                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
673                 return false;\r
674         }\r
675         if (sec->SessionCreated == false)\r
676         {\r
677                 sec->Error = SEC_ERROR_NO_SESSION;\r
678                 return false;\r
679         }\r
680         if (sec->LoginFlag == false && private_obj)\r
681         {\r
682                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
683                 return false;\r
684         }\r
685 \r
686         // 証明書をバッファにコピー\r
687         b = XToBuf(x, false);\r
688         if (b == NULL)\r
689         {\r
690                 sec->Error = SEC_ERROR_INVALID_CERT;\r
691                 return false;\r
692         }\r
693         if (b->Size > sizeof(value))\r
694         {\r
695                 // サイズが大きすぎる\r
696                 FreeBuf(b);\r
697                 sec->Error = SEC_ERROR_DATA_TOO_BIG;\r
698                 return false;\r
699         }\r
700         Copy(value, b->Buf, b->Size);\r
701         A_SIZE(a, 3) = b->Size;\r
702         FreeBuf(b);\r
703 \r
704         // Subject と Issuer を UTF-8 にエンコードして格納\r
705         GetPrintNameFromName(w_subject, sizeof(w_subject), x->subject_name);\r
706         UniToUtf8(subject, sizeof(subject), w_subject);\r
707         A_SIZE(a, 0) = StrLen(subject);\r
708         if (x->root_cert == false)\r
709         {\r
710                 GetPrintNameFromName(w_issuer, sizeof(w_issuer), x->issuer_name);\r
711                 UniToUtf8(issuer, sizeof(issuer), w_issuer);\r
712                 A_SIZE(a, 1) = StrLen(issuer);\r
713         }\r
714 \r
715         // シリアル番号をコピー\r
716         Copy(serial_number, x->serial->data, MIN(x->serial->size, sizeof(serial_number)));\r
717         A_SIZE(a, 2) = MIN(x->serial->size, sizeof(serial_number));\r
718 \r
719         // 有効期限情報\r
720         UINT64ToCkDate(&start_date, SystemToLocal64(x->notBefore));\r
721         UINT64ToCkDate(&end_date, SystemToLocal64(x->notAfter));\r
722 \r
723         // 同一の名前のオブジェクトがあれば削除\r
724         if (CheckSecObject(sec, name, SEC_X))\r
725         {\r
726                 DeleteSecCert(sec, name);\r
727         }\r
728 \r
729         // 作成\r
730         if ((ret = sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object)) != CKR_OK)\r
731         {\r
732                 // 失敗\r
733                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
734                 Debug("Error: 0x%02x\n", ret);\r
735                 return false;\r
736         }\r
737 \r
738         // キャッシュ消去\r
739         EraseEnumSecObjectCache(sec);\r
740 \r
741         return true;\r
742 }\r
743 \r
744 // 秘密鍵オブジェクトの削除\r
745 bool DeleteSecKey(SECURE *sec, char *name)\r
746 {\r
747         return DeleteSecObjectByName(sec, name, SEC_K);\r
748 }\r
749 \r
750 // 証明書オブジェクトの削除\r
751 bool DeleteSecCert(SECURE *sec, char *name)\r
752 {\r
753         return DeleteSecObjectByName(sec, name, SEC_X);\r
754 }\r
755 \r
756 // CK_DATE を 64 bit 時刻に変換\r
757 UINT64 CkDateToUINT64(struct CK_DATE *ck_date)\r
758 {\r
759         SYSTEMTIME st;\r
760         char year[32], month[32], day[32];\r
761         // 引数チェック\r
762         if (ck_date == NULL)\r
763         {\r
764                 return 0;\r
765         }\r
766 \r
767         Zero(year, sizeof(year));\r
768         Zero(month, sizeof(month));\r
769         Zero(day, sizeof(day));\r
770 \r
771         Copy(year, ck_date->year, 4);\r
772         Copy(month, ck_date->month, 2);\r
773         Copy(day, ck_date->day, 2);\r
774 \r
775         st.wYear = ToInt(year);\r
776         st.wMonth = ToInt(month);\r
777         st.wDay = ToInt(day);\r
778 \r
779         return SystemToUINT64(&st);\r
780 }\r
781 \r
782 // 64 bit 時刻を CK_DATE に変換\r
783 void UINT64ToCkDate(void *p_ck_date, UINT64 time64)\r
784 {\r
785         SYSTEMTIME st;\r
786         char year[32], month[32], day[32];\r
787         struct CK_DATE *ck_date = (CK_DATE *)p_ck_date;\r
788         // 引数チェック\r
789         if (ck_date == NULL)\r
790         {\r
791                 return;\r
792         }\r
793 \r
794         UINT64ToSystem(&st, time64);\r
795 \r
796         Format(year, sizeof(year), "%04u", st.wYear);\r
797         Format(month, sizeof(month), "%04u", st.wMonth);\r
798         Format(day, sizeof(day), "%04u", st.wDay);\r
799 \r
800         Zero(ck_date, sizeof(CK_DATE));\r
801 \r
802         Copy(ck_date->year, year, 4);\r
803         Copy(ck_date->month, month, 2);\r
804         Copy(ck_date->day, day, 2);\r
805 }\r
806 \r
807 // オブジェクトを名前で指定して削除\r
808 bool DeleteSecObjectByName(SECURE *sec, char *name, UINT type)\r
809 {\r
810         bool ret;\r
811         SEC_OBJ *obj;\r
812         // 引数チェック\r
813         if (sec == NULL)\r
814         {\r
815                 return false;\r
816         }\r
817         if (name == NULL)\r
818         {\r
819                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
820                 return false;\r
821         }\r
822         if (sec->SessionCreated == false)\r
823         {\r
824                 sec->Error = SEC_ERROR_NO_SESSION;\r
825                 return false;\r
826         }\r
827 \r
828         // オブジェクト取得\r
829         obj = FindSecObject(sec, name, type);\r
830         if (obj == NULL)\r
831         {\r
832                 // 失敗\r
833                 return false;\r
834         }\r
835 \r
836         // オブジェクト削除\r
837         ret = DeleteSecObject(sec, obj);\r
838 \r
839         // メモリ解放\r
840         FreeSecObject(obj);\r
841 \r
842         return ret;\r
843 }\r
844 \r
845 // データの削除\r
846 bool DeleteSecData(SECURE *sec, char *name)\r
847 {\r
848         // 引数チェック\r
849         if (sec == NULL)\r
850         {\r
851                 return false;\r
852         }\r
853         if (name == NULL)\r
854         {\r
855                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
856                 return false;\r
857         }\r
858 \r
859         return DeleteSecObjectByName(sec, name, SEC_DATA);\r
860 }\r
861 \r
862 // セキュアオブジェクトの削除\r
863 bool DeleteSecObject(SECURE *sec, SEC_OBJ *obj)\r
864 {\r
865         // 引数チェック\r
866         if (sec == NULL)\r
867         {\r
868                 return false;\r
869         }\r
870         if (obj == NULL)\r
871         {\r
872                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
873                 return false;\r
874         }\r
875         if (sec->SessionCreated == false)\r
876         {\r
877                 sec->Error = SEC_ERROR_NO_SESSION;\r
878                 return false;\r
879         }\r
880         if (sec->LoginFlag == false && obj->Private)\r
881         {\r
882                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
883                 return false;\r
884         }\r
885 \r
886         // オブジェクト消去\r
887         if (sec->Api->C_DestroyObject(sec->SessionId, obj->Object) != CKR_OK)\r
888         {\r
889                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
890                 return false;\r
891         }\r
892 \r
893         // キャッシュ消去\r
894         DeleteSecObjFromEnumCache(sec, obj->Name, obj->Type);\r
895 \r
896         return true;\r
897 }\r
898 \r
899 // キャッシュから指定した名前のオブジェクトを削除する\r
900 void DeleteSecObjFromEnumCache(SECURE *sec, char *name, UINT type)\r
901 {\r
902         UINT i;\r
903         // 引数チェック\r
904         if (sec == NULL || name == NULL || sec->EnumCache == NULL)\r
905         {\r
906                 return;\r
907         }\r
908 \r
909         for (i = 0;i < LIST_NUM(sec->EnumCache);i++)\r
910         {\r
911                 SEC_OBJ *obj = LIST_DATA(sec->EnumCache, i);\r
912 \r
913                 if (StrCmpi(obj->Name, name) == 0)\r
914                 {\r
915                         if (obj->Type == type)\r
916                         {\r
917                                 Delete(sec->EnumCache, obj);\r
918                                 FreeSecObject(obj);\r
919                                 break;\r
920                         }\r
921                 }\r
922         }\r
923 }\r
924 \r
925 // セキュアオブジェクトを名前で検索して読み込む\r
926 int ReadSecData(SECURE *sec, char *name, void *data, UINT size)\r
927 {\r
928         UINT ret = 0;\r
929         SEC_OBJ *obj;\r
930         // 引数チェック\r
931         if (sec == NULL || name == NULL || data == NULL)\r
932         {\r
933                 return 0;\r
934         }\r
935         if (sec->SessionCreated == false)\r
936         {\r
937                 sec->Error = SEC_ERROR_NO_SESSION;\r
938                 return 0;\r
939         }\r
940 \r
941         // 読み込み\r
942         obj = FindSecObject(sec, name, SEC_DATA);\r
943         if (obj == NULL)\r
944         {\r
945                 // 見つからない\r
946                 return 0;\r
947         }\r
948 \r
949         // 読み込む\r
950         ret = ReadSecDataFromObject(sec, obj, data, size);\r
951 \r
952         FreeSecObject(obj);\r
953 \r
954         return ret;\r
955 }\r
956 \r
957 // キャッシュ消去\r
958 void EraseEnumSecObjectCache(SECURE *sec)\r
959 {\r
960         // 引数チェック\r
961         if (sec == NULL || sec->EnumCache == NULL)\r
962         {\r
963                 return;\r
964         }\r
965 \r
966         FreeEnumSecObject(sec->EnumCache);\r
967         sec->EnumCache = NULL;\r
968 }\r
969 \r
970 // セキュアオブジェクトの存在をチェックする\r
971 bool CheckSecObject(SECURE *sec, char *name, UINT type)\r
972 {\r
973         SEC_OBJ *obj;\r
974         // 引数チェック\r
975         if (sec == NULL)\r
976         {\r
977                 return false;\r
978         }\r
979         if (name == NULL)\r
980         {\r
981                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
982                 return false;\r
983         }\r
984         if (sec->SessionCreated == false)\r
985         {\r
986                 sec->Error = SEC_ERROR_NO_SESSION;\r
987                 return 0;\r
988         }\r
989 \r
990         obj = FindSecObject(sec, name, type);\r
991 \r
992         if (obj == NULL)\r
993         {\r
994                 return false;\r
995         }\r
996         else\r
997         {\r
998                 FreeSecObject(obj);\r
999                 return true;\r
1000         }\r
1001 }\r
1002 \r
1003 // セキュアオブジェクト構造体のクローンの作成\r
1004 SEC_OBJ *CloneSecObject(SEC_OBJ *obj)\r
1005 {\r
1006         SEC_OBJ *ret;\r
1007         // 引数チェック\r
1008         if (obj == NULL)\r
1009         {\r
1010                 return NULL;\r
1011         }\r
1012 \r
1013         ret = ZeroMalloc(sizeof(SEC_OBJ));\r
1014         ret->Name = CopyStr(obj->Name);\r
1015         ret->Object = obj->Object;\r
1016         ret->Private = obj->Private;\r
1017         ret->Type = obj->Type;\r
1018 \r
1019         return ret;\r
1020 }\r
1021 \r
1022 // セキュアオブジェクトを名前で検索して取得する\r
1023 SEC_OBJ *FindSecObject(SECURE *sec, char *name, UINT type)\r
1024 {\r
1025         LIST *o;\r
1026         UINT i;\r
1027         SEC_OBJ *ret = NULL;\r
1028         // 引数チェック\r
1029         if (sec == NULL)\r
1030         {\r
1031                 return NULL;\r
1032         }\r
1033         if (name == NULL)\r
1034         {\r
1035                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
1036                 return NULL;\r
1037         }\r
1038         if (sec->SessionCreated == false)\r
1039         {\r
1040                 sec->Error = SEC_ERROR_NO_SESSION;\r
1041                 return 0;\r
1042         }\r
1043 \r
1044         // 列挙\r
1045         o = EnumSecObject(sec);\r
1046         if (o == NULL)\r
1047         {\r
1048                 return NULL;\r
1049         }\r
1050         for (i = 0;i < LIST_NUM(o);i++)\r
1051         {\r
1052                 SEC_OBJ *obj = LIST_DATA(o, i);\r
1053 \r
1054                 if (obj->Type == type || type == INFINITE)\r
1055                 {\r
1056                         if (StrCmpi(obj->Name, name) == 0)\r
1057                         {\r
1058                                 ret = CloneSecObject(obj);\r
1059                                 break;\r
1060                         }\r
1061                 }\r
1062         }\r
1063         FreeEnumSecObject(o);\r
1064 \r
1065         if (ret == NULL)\r
1066         {\r
1067                 sec->Error = SEC_ERROR_OBJ_NOT_FOUND;\r
1068         }\r
1069 \r
1070         return ret;\r
1071 }\r
1072 \r
1073 // セキュアオブジェクトの読み込み\r
1074 int ReadSecDataFromObject(SECURE *sec, SEC_OBJ *obj, void *data, UINT size)\r
1075 {\r
1076         UCHAR buf[MAX_SEC_DATA_SIZE];\r
1077         UINT i;\r
1078         CK_ATTRIBUTE get[] =\r
1079         {\r
1080                 {CKA_VALUE,      buf,   sizeof(buf)},\r
1081         };\r
1082         // 引数チェック\r
1083         if (sec == NULL)\r
1084         {\r
1085                 return 0;\r
1086         }\r
1087         if (obj == NULL || data == NULL || size == 0)\r
1088         {\r
1089                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
1090                 return 0;\r
1091         }\r
1092         if (obj->Type != SEC_DATA)\r
1093         {\r
1094                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
1095                 return false;\r
1096         }\r
1097         if (sec->SessionCreated == false)\r
1098         {\r
1099                 sec->Error = SEC_ERROR_NO_SESSION;\r
1100                 return 0;\r
1101         }\r
1102         if (sec->LoginFlag == false && obj->Private)\r
1103         {\r
1104                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
1105                 return 0;\r
1106         }\r
1107 \r
1108         // 取得\r
1109         if (sec->Api->C_GetAttributeValue(\r
1110                 sec->SessionId, obj->Object, get, sizeof(get) / sizeof(get[0])) != CKR_OK)\r
1111         {\r
1112                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
1113                 return 0;\r
1114         }\r
1115 \r
1116         // 結果の返却\r
1117         i = get[0].ulValueLen;\r
1118         if (i > MAX_SEC_DATA_SIZE || i > size)\r
1119         {\r
1120                 // データが大きすぎる\r
1121                 sec->Error = SEC_ERROR_DATA_TOO_BIG;\r
1122                 return 0;\r
1123         }\r
1124 \r
1125         // メモリコピー\r
1126         Copy(data, buf, i);\r
1127 \r
1128         return i;\r
1129 }\r
1130 \r
1131 // セキュアオブジェクトの列挙結果の解放\r
1132 void FreeEnumSecObject(LIST *o)\r
1133 {\r
1134         UINT i;\r
1135         // 引数チェック\r
1136         if (o == NULL)\r
1137         {\r
1138                 return;\r
1139         }\r
1140 \r
1141         for (i = 0;i < LIST_NUM(o);i++)\r
1142         {\r
1143                 SEC_OBJ *obj = LIST_DATA(o, i);\r
1144 \r
1145                 FreeSecObject(obj);\r
1146         }\r
1147 \r
1148         ReleaseList(o);\r
1149 }\r
1150 \r
1151 // セキュアオブジェクトの解放\r
1152 void FreeSecObject(SEC_OBJ *obj)\r
1153 {\r
1154         // 引数チェック\r
1155         if (obj == NULL)\r
1156         {\r
1157                 return;\r
1158         }\r
1159 \r
1160         Free(obj->Name);\r
1161         Free(obj);\r
1162 }\r
1163 \r
1164 // セキュアオブジェクト列挙結果のクローン\r
1165 LIST *CloneEnumSecObject(LIST *o)\r
1166 {\r
1167         LIST *ret;\r
1168         UINT i;\r
1169         // 引数チェック\r
1170         if (o == NULL)\r
1171         {\r
1172                 return NULL;\r
1173         }\r
1174 \r
1175         ret = NewListFast(NULL);\r
1176         for (i = 0;i < LIST_NUM(o);i++)\r
1177         {\r
1178                 SEC_OBJ *obj = LIST_DATA(o, i);\r
1179 \r
1180                 Add(ret, CloneSecObject(obj));\r
1181         }\r
1182 \r
1183         return ret;\r
1184 }\r
1185 \r
1186 // セキュアオブジェクトの列挙\r
1187 LIST *EnumSecObject(SECURE *sec)\r
1188 {\r
1189         CK_BBOOL b_true = true, b_false = false;\r
1190         UINT objects[MAX_OBJ];\r
1191         UINT i;\r
1192         UINT ret;\r
1193         LIST *o;\r
1194         CK_ATTRIBUTE dummy[1];\r
1195         CK_ATTRIBUTE a[] =\r
1196         {\r
1197                 {CKA_TOKEN,             &b_true,                sizeof(b_true)},\r
1198         };\r
1199         UINT num_objects = MAX_OBJ;\r
1200         // 引数チェック\r
1201         if (sec == NULL)\r
1202         {\r
1203                 return NULL;\r
1204         }\r
1205         if (sec->SessionCreated == false)\r
1206         {\r
1207                 sec->Error = SEC_ERROR_NO_SESSION;\r
1208                 return NULL;\r
1209         }\r
1210 \r
1211         Zero(dummy, sizeof(dummy));\r
1212 \r
1213         // キャッシュがあればキャッシュを返す\r
1214         if (sec->EnumCache != NULL)\r
1215         {\r
1216                 return CloneEnumSecObject(sec->EnumCache);\r
1217         }\r
1218 \r
1219         // 列挙\r
1220 //      if (sec->Dev->Id != 2 && sec->Dev->Id != 14)\r
1221 //      {\r
1222                 // 通常のトークン\r
1223                 ret = sec->Api->C_FindObjectsInit(sec->SessionId, a, sizeof(a) / sizeof(a[0]));\r
1224 //      }\r
1225 //      else\r
1226 //      {\r
1227                 // ePass と SafeSign\r
1228 //              ret = sec->Api->C_FindObjectsInit(sec->SessionId, dummy, 0);\r
1229 //      }\r
1230 \r
1231         if (ret != CKR_OK)\r
1232         {\r
1233                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
1234                 return NULL;\r
1235         }\r
1236         if (sec->Api->C_FindObjects(sec->SessionId, objects, sizeof(objects) / sizeof(objects[0]), &num_objects) != CKR_OK)\r
1237         {\r
1238                 sec->Api->C_FindObjectsFinal(sec->SessionId);\r
1239                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
1240                 return NULL;\r
1241         }\r
1242         sec->Api->C_FindObjectsFinal(sec->SessionId);\r
1243 \r
1244         o = NewListFast(NULL);\r
1245 \r
1246         for (i = 0;i < num_objects;i++)\r
1247         {\r
1248                 char label[MAX_SIZE];\r
1249                 UINT obj_class = 0;\r
1250                 bool priv = false;\r
1251                 CK_ATTRIBUTE get[] =\r
1252                 {\r
1253                         {CKA_LABEL, label, sizeof(label) - 1},\r
1254                         {CKA_CLASS, &obj_class, sizeof(obj_class)},\r
1255                         {CKA_PRIVATE, &priv, sizeof(priv)},\r
1256                 };\r
1257 \r
1258                 Zero(label, sizeof(label));\r
1259 \r
1260                 if (sec->Api->C_GetAttributeValue(sec->SessionId, objects[i],\r
1261                         get, sizeof(get) / sizeof(get[0])) == CKR_OK)\r
1262                 {\r
1263                         UINT type = INFINITE;\r
1264 \r
1265                         switch (obj_class)\r
1266                         {\r
1267                         case CKO_DATA:\r
1268                                 // データ\r
1269                                 type = SEC_DATA;\r
1270                                 break;\r
1271 \r
1272                         case CKO_CERTIFICATE:\r
1273                                 // 証明書\r
1274                                 type = SEC_X;\r
1275                                 break;\r
1276 \r
1277                         case CKO_PUBLIC_KEY:\r
1278                                 // 公開鍵\r
1279                                 type = SEC_P;\r
1280                                 break;\r
1281 \r
1282                         case CKO_PRIVATE_KEY:\r
1283                                 // 秘密鍵\r
1284                                 type = SEC_K;\r
1285                                 break;\r
1286                         }\r
1287 \r
1288                         if (type != INFINITE)\r
1289                         {\r
1290                                 SEC_OBJ *obj = ZeroMalloc(sizeof(SEC_OBJ));\r
1291 \r
1292                                 obj->Type = type;\r
1293                                 obj->Object = objects[i];\r
1294                                 obj->Private = (priv == false) ? false : true;\r
1295                                 EnSafeStr(label, '?');\r
1296                                 TruncateCharFromStr(label, '?');\r
1297                                 obj->Name = CopyStr(label);\r
1298 \r
1299                                 Add(o, obj);\r
1300                         }\r
1301                 }\r
1302         }\r
1303 \r
1304         // キャッシュ作成\r
1305         sec->EnumCache = CloneEnumSecObject(o);\r
1306 \r
1307         return o;\r
1308 }\r
1309 \r
1310 // データを書き込む\r
1311 bool WriteSecData(SECURE *sec, bool private_obj, char *name, void *data, UINT size)\r
1312 {\r
1313         UINT object_class = CKO_DATA;\r
1314         CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;\r
1315         UINT object;\r
1316         CK_ATTRIBUTE a[] =\r
1317         {\r
1318                 {CKA_TOKEN,             &b_true,                sizeof(b_true)},\r
1319                 {CKA_CLASS,             &object_class,  sizeof(object_class)},\r
1320                 {CKA_PRIVATE,   &b_private_obj, sizeof(b_private_obj)},\r
1321                 {CKA_LABEL,             name,                   StrLen(name)},\r
1322                 {CKA_VALUE,             data,                   size},\r
1323         };\r
1324         // 引数チェック\r
1325         if (sec == NULL)\r
1326         {\r
1327                 return false;\r
1328         }\r
1329         if (sec->SessionCreated == false)\r
1330         {\r
1331                 sec->Error = SEC_ERROR_NO_SESSION;\r
1332                 return false;\r
1333         }\r
1334         if (private_obj && sec->LoginFlag == false)\r
1335         {\r
1336                 sec->Error = SEC_ERROR_NOT_LOGIN;\r
1337                 return false;\r
1338         }\r
1339         if (name == NULL || data == NULL || size == 0)\r
1340         {\r
1341                 sec->Error = SEC_ERROR_BAD_PARAMETER;\r
1342                 return false;\r
1343         }\r
1344         if (size > MAX_SEC_DATA_SIZE)\r
1345         {\r
1346                 sec->Error = SEC_ERROR_DATA_TOO_BIG;\r
1347                 return false;\r
1348         }\r
1349 \r
1350         // 同名のオブジェクトがあれば削除\r
1351         if (CheckSecObject(sec, name, SEC_DATA))\r
1352         {\r
1353                 DeleteSecData(sec, name);\r
1354         }\r
1355 \r
1356         // オブジェクト作成\r
1357         if (sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object) != CKR_OK)\r
1358         {\r
1359                 sec->Error = SEC_ERROR_HARDWARE_ERROR;\r
1360                 return false;\r
1361         }\r
1362 \r
1363         // キャッシュ消去\r
1364         EraseEnumSecObjectCache(sec);\r
1365 \r
1366         return true;\r
1367 }\r
1368 \r
1369 // キャッシュに新規作成したオブジェクトの情報を追加する\r
1370 void AddSecObjToEnumCache(SECURE *sec, char *name, UINT type, bool private_obj, UINT object)\r
1371 {\r
1372         SEC_OBJ *obj;\r
1373         // 引数チェック\r
1374         if (sec == NULL || name == NULL || sec->EnumCache == NULL)\r
1375         {\r
1376                 return;\r
1377         }\r
1378 \r
1379         obj = ZeroMalloc(sizeof(SEC_OBJ));\r
1380         obj->Name = CopyStr(name);\r
1381         obj->Object = object;\r
1382         obj->Private = private_obj;\r
1383         obj->Type = type;\r
1384 \r
1385         Add(sec->EnumCache, obj);\r
1386 }\r
1387 \r
1388 // トークン情報を表示\r
1389 void PrintSecInfo(SECURE *sec)\r
1390 {\r
1391         SEC_INFO *s;\r
1392         // 引数チェック\r
1393         if (sec == NULL)\r
1394         {\r
1395                 return;\r
1396         }\r
1397 \r
1398         s = sec->Info;\r
1399         if (s == NULL)\r
1400         {\r
1401                 Print("No Token Info.\n");\r
1402                 return;\r
1403         }\r
1404 \r
1405         Print(\r
1406                 "               Label: %S\n"\r
1407                 "      ManufacturerId: %S\n"\r
1408                 "               Model: %S\n"\r
1409                 "        SerialNumber: %S\n"\r
1410                 "          MaxSession: %u\n"\r
1411                 "        MaxRWSession: %u\n"\r
1412                 "           MinPinLen: %u\n"\r
1413                 "           MaxPinLen: %u\n"\r
1414                 "   TotalPublicMemory: %u\n"\r
1415                 "    FreePublicMemory: %u\n"\r
1416                 "  TotalPrivateMemory: %u\n"\r
1417                 "   FreePrivateMemory: %u\n"\r
1418                 "     HardwareVersion: %s\n"\r
1419                 "     FirmwareVersion: %s\n",\r
1420                 s->Label, s->ManufacturerId, s->Model, s->SerialNumber,\r
1421                 s->MaxSession, s->MaxRWSession, s->MinPinLen, s->MaxPinLen,\r
1422                 s->TotalPublicMemory, s->FreePublicMemory, s->TotalPrivateMemory,\r
1423                 s->FreePrivateMemory, s->HardwareVersion, s->FirmwareVersion\r
1424                 );\r
1425 }\r
1426 \r
1427 // トークン情報を取得\r
1428 void GetSecInfo(SECURE *sec)\r
1429 {\r
1430         CK_TOKEN_INFO token_info;\r
1431         // 引数チェック\r
1432         if (sec == NULL)\r
1433         {\r
1434                 return;\r
1435         }\r
1436         if (sec->Info != NULL)\r
1437         {\r
1438                 return;\r
1439         }\r
1440 \r
1441         // 取得\r
1442         Zero(&token_info, sizeof(token_info));\r
1443         if (sec->Api->C_GetTokenInfo(sec->SlotIdList[sec->SessionSlotNumber], &token_info) != CKR_OK)\r
1444         {\r
1445                 // 失敗\r
1446                 return;\r
1447         }\r
1448 \r
1449         sec->Info = TokenInfoToSecInfo(&token_info);\r
1450 }\r
1451 \r
1452 // トークン情報を解放\r
1453 void FreeSecInfo(SECURE *sec)\r
1454 {\r
1455         // 引数チェック\r
1456         if (sec == NULL)\r
1457         {\r
1458                 return;\r
1459         }\r
1460         if (sec->Info == NULL)\r
1461         {\r
1462                 return;\r
1463         }\r
1464 \r
1465         FreeSecInfoMemory(sec->Info);\r
1466         sec->Info = NULL;\r
1467 }\r
1468 \r
1469 // トークン情報を SEC_INFO に変換\r
1470 SEC_INFO *TokenInfoToSecInfo(void *p_t)\r
1471 {\r
1472         SEC_INFO *s;\r
1473         char buf[MAX_SIZE];\r
1474         CK_TOKEN_INFO *t = (CK_TOKEN_INFO *)p_t;\r
1475         // 引数チェック\r
1476         if (t == NULL)\r
1477         {\r
1478                 return NULL;\r
1479         }\r
1480 \r
1481         s = ZeroMalloc(sizeof(SEC_INFO));\r
1482 \r
1483         // Label\r
1484         Zero(buf, sizeof(buf));\r
1485         Copy(buf, t->label, sizeof(t->label));\r
1486         s->Label = ZeroMalloc(CalcUtf8ToUni(buf, 0));\r
1487         Utf8ToUni(s->Label, 0, buf, 0);\r
1488 \r
1489         // ManufacturerId\r
1490         Zero(buf, sizeof(buf));\r
1491         Copy(buf, t->manufacturerID, sizeof(t->manufacturerID));\r
1492         s->ManufacturerId = ZeroMalloc(CalcUtf8ToUni(buf, 0));\r
1493         Utf8ToUni(s->ManufacturerId, 0, buf, 0);\r
1494 \r
1495         // Model\r
1496         Zero(buf, sizeof(buf));\r
1497         Copy(buf, t->model, sizeof(t->model));\r
1498         s->Model = ZeroMalloc(CalcUtf8ToUni(buf, 0));\r
1499         Utf8ToUni(s->Model, 0, buf, 0);\r
1500 \r
1501         // SerialNumber\r
1502         Zero(buf, sizeof(buf));\r
1503         Copy(buf, t->serialNumber, sizeof(t->serialNumber));\r
1504         s->SerialNumber = ZeroMalloc(CalcUtf8ToUni(buf, 0));\r
1505         Utf8ToUni(s->SerialNumber, 0, buf, 0);\r
1506 \r
1507         // 数値\r
1508         s->MaxSession = t->ulMaxSessionCount;\r
1509         s->MaxRWSession = t->ulMaxRwSessionCount;\r
1510         s->MinPinLen = t->ulMinPinLen;\r
1511         s->MaxPinLen = t->ulMaxPinLen;\r
1512         s->TotalPublicMemory = t->ulTotalPublicMemory;\r
1513         s->FreePublicMemory = t->ulFreePublicMemory;\r
1514         s->TotalPrivateMemory = t->ulTotalPrivateMemory;\r
1515         s->FreePrivateMemory = t->ulFreePrivateMemory;\r
1516 \r
1517         // ハードウェアバージョン\r
1518         Format(buf, sizeof(buf), "%u.%02u", t->hardwareVersion.major, t->hardwareVersion.minor);\r
1519         s->HardwareVersion = CopyStr(buf);\r
1520 \r
1521         // ファームウェアバージョン\r
1522         Format(buf, sizeof(buf), "%u.%02u", t->firmwareVersion.major, t->firmwareVersion.minor);\r
1523         s->FirmwareVersion = CopyStr(buf);\r
1524 \r
1525         return s;\r
1526 }\r
1527 \r
1528 // SEC_INFO のメモリを解放\r
1529 void FreeSecInfoMemory(SEC_INFO *s)\r
1530 {\r
1531         // 引数チェック\r
1532         if (s == NULL)\r
1533         {\r
1534                 return;\r
1535         }\r
1536 \r
1537         Free(s->Label);\r
1538         Free(s->ManufacturerId);\r
1539         Free(s->Model);\r
1540         Free(s->SerialNumber);\r
1541         Free(s->HardwareVersion);\r
1542         Free(s->FirmwareVersion);\r
1543         Free(s);\r
1544 }\r
1545 \r
1546 // ログアウトする\r
1547 void LogoutSec(SECURE *sec)\r
1548 {\r
1549         // 引数チェック\r
1550         if (sec == NULL)\r
1551         {\r
1552                 return;\r
1553         }\r
1554         if (sec->LoginFlag == false)\r
1555         {\r
1556                 return;\r
1557         }\r
1558 \r
1559         // ログアウト\r
1560         sec->Api->C_Logout(sec->SessionId);\r
1561 \r
1562         // キャッシュ消去\r
1563         EraseEnumSecObjectCache(sec);\r
1564 \r
1565         sec->LoginFlag = false;\r
1566 }\r
1567 \r
1568 // ログインする\r
1569 bool LoginSec(SECURE *sec, char *pin)\r
1570 {\r
1571         // 引数チェック\r
1572         if (sec == NULL)\r
1573         {\r
1574                 return false;\r
1575         }\r
1576         if (sec->SessionCreated == false)\r
1577         {\r
1578                 sec->Error = SEC_ERROR_NO_SESSION;\r
1579                 return false;\r
1580 \r
1581         }\r
1582         if (sec->LoginFlag)\r
1583         {\r
1584                 sec->Error = SEC_ERROR_ALREADY_LOGIN;\r
1585                 return false;\r
1586         }\r
1587         if (pin == NULL)\r
1588         {\r
1589                 sec->Error = SEC_ERROR_NO_PIN_STR;\r
1590                 return false;\r
1591         }\r
1592 \r
1593         // ログイン\r
1594         if (sec->Api->C_Login(sec->SessionId, CKU_USER, pin, StrLen(pin)) != CKR_OK)\r
1595         {\r
1596                 // ログイン失敗\r
1597                 sec->Error = SEC_ERROR_BAD_PIN_CODE;\r
1598                 return false;\r
1599         }\r
1600 \r
1601         // キャッシュ消去\r
1602         EraseEnumSecObjectCache(sec);\r
1603 \r
1604         sec->LoginFlag = true;\r
1605 \r
1606         return true;\r
1607 }\r
1608 \r
1609 // セッションを閉じる\r
1610 void CloseSecSession(SECURE *sec)\r
1611 {\r
1612         // 引数チェック\r
1613         if (sec == NULL)\r
1614         {\r
1615                 return;\r
1616         }\r
1617         if (sec->SessionCreated == false)\r
1618         {\r
1619                 return;\r
1620         }\r
1621 \r
1622         // セッションを閉じる\r
1623         sec->Api->C_CloseSession(sec->SessionId);\r
1624 \r
1625         sec->SessionCreated = false;\r
1626         sec->SessionId = 0;\r
1627         sec->SessionSlotNumber = 0;\r
1628 \r
1629         FreeSecInfo(sec);\r
1630 \r
1631         // キャッシュ消去\r
1632         EraseEnumSecObjectCache(sec);\r
1633 }\r
1634 \r
1635 // セッションを開く\r
1636 bool OpenSecSession(SECURE *sec, UINT slot_number)\r
1637 {\r
1638         UINT err = 0;\r
1639         UINT session;\r
1640         // 引数チェック\r
1641         if (sec == NULL)\r
1642         {\r
1643                 return false;\r
1644         }\r
1645         if (sec->SessionCreated)\r
1646         {\r
1647                 // すでに作成されている\r
1648                 sec->Error = SEC_ERROR_SESSION_EXISTS;\r
1649                 return false;\r
1650         }\r
1651         if (slot_number >= sec->NumSlot)\r
1652         {\r
1653                 // スロット番号不正\r
1654                 sec->Error = SEC_ERROR_INVALID_SLOT_NUMBER;\r
1655                 return false;\r
1656         }\r
1657 \r
1658         // セッション作成\r
1659         if ((err = sec->Api->C_OpenSession(sec->SlotIdList[slot_number],\r
1660                 CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK)\r
1661         {\r
1662                 // 読み書きモードでのセッション初期化に失敗した\r
1663                 // 読み取り専用モードかな?\r
1664                 if ((err = sec->Api->C_OpenSession(sec->SlotIdList[slot_number],\r
1665                         CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK)\r
1666                 {\r
1667                         // 作成失敗\r
1668                         sec->Error = SEC_ERROR_OPEN_SESSION;\r
1669                         return false;\r
1670                 }\r
1671                 else\r
1672                 {\r
1673                         sec->IsReadOnly = true;\r
1674                 }\r
1675         }\r
1676 \r
1677         sec->SessionCreated = true;\r
1678         sec->SessionId = session;\r
1679         sec->SessionSlotNumber = slot_number;\r
1680 \r
1681         // トークン情報を取得\r
1682         GetSecInfo(sec);\r
1683 \r
1684         return true;\r
1685 }\r
1686 \r
1687 // セキュアデバイスを閉じる\r
1688 void CloseSec(SECURE *sec)\r
1689 {\r
1690         // 引数チェック\r
1691         if (sec == NULL)\r
1692         {\r
1693                 return;\r
1694         }\r
1695 \r
1696         // ログアウトする\r
1697         LogoutSec(sec);\r
1698 \r
1699         // セッションを閉じる\r
1700         CloseSecSession(sec);\r
1701 \r
1702         // トークン情報を解放\r
1703         FreeSecInfo(sec);\r
1704 \r
1705         // スロットリストメモリの解放\r
1706         if (sec->SlotIdList != NULL)\r
1707         {\r
1708                 Free(sec->SlotIdList);\r
1709                 sec->SlotIdList = NULL;\r
1710         }\r
1711 \r
1712         // モジュールのアンロード\r
1713         FreeSecModule(sec);\r
1714 \r
1715         // メモリ解放\r
1716         DeleteLock(sec->lock);\r
1717         Free(sec);\r
1718 }\r
1719 \r
1720 // セキュアデバイスを開く\r
1721 SECURE *OpenSec(UINT id)\r
1722 {\r
1723         SECURE_DEVICE *dev = GetSecureDevice(id);\r
1724         SECURE *sec;\r
1725         UINT err;\r
1726 \r
1727         if (dev == NULL)\r
1728         {\r
1729                 return NULL;\r
1730         }\r
1731 \r
1732         sec = ZeroMalloc(sizeof(SECURE));\r
1733 \r
1734         sec->lock = NewLock();\r
1735         sec->Error = SEC_ERROR_NOERROR;\r
1736         sec->Dev = dev;\r
1737 \r
1738         // ePass かどうか取得する\r
1739         if (SearchStrEx(dev->DeviceName, "epass", 0, false) != INFINITE)\r
1740         {\r
1741                 sec->IsEPass1000 = true;\r
1742         }\r
1743 \r
1744         // モジュールのロード\r
1745         if (LoadSecModule(sec) == false)\r
1746         {\r
1747                 CloseSec(sec);\r
1748                 return NULL;\r
1749         }\r
1750 \r
1751         // スロット一覧の取得\r
1752         sec->NumSlot = 0;\r
1753         if ((err = sec->Api->C_GetSlotList(true, NULL, &sec->NumSlot)) != CKR_OK || sec->NumSlot == 0)\r
1754         {\r
1755                 // 失敗\r
1756                 FreeSecModule(sec);\r
1757                 CloseSec(sec);\r
1758                 return NULL;\r
1759         }\r
1760 \r
1761         sec->SlotIdList = (UINT *)ZeroMalloc(sizeof(UINT *) * sec->NumSlot);\r
1762 \r
1763         if (sec->Api->C_GetSlotList(TRUE, sec->SlotIdList, &sec->NumSlot) != CKR_OK)\r
1764         {\r
1765                 // 失敗\r
1766                 Free(sec->SlotIdList);\r
1767                 sec->SlotIdList = NULL;\r
1768                 FreeSecModule(sec);\r
1769                 CloseSec(sec);\r
1770                 return NULL;\r
1771         }\r
1772 \r
1773         return sec;\r
1774 }\r
1775 \r
1776 // セキュアデバイスのモジュールをロードする\r
1777 bool LoadSecModule(SECURE *sec)\r
1778 {\r
1779         bool ret = false;\r
1780         // 引数チェック\r
1781         if (sec == NULL)\r
1782         {\r
1783                 return false;\r
1784         }\r
1785 \r
1786 #ifdef  OS_WIN32\r
1787         ret = Win32LoadSecModule(sec);\r
1788 #endif  // OS_WIN32\r
1789 \r
1790         // 初期化\r
1791         if (sec->Api->C_Initialize(NULL) != CKR_OK)\r
1792         {\r
1793                 // 初期化失敗\r
1794                 FreeSecModule(sec);\r
1795                 return false;\r
1796         }\r
1797 \r
1798         sec->Initialized = true;\r
1799 \r
1800         return ret;\r
1801 }\r
1802 \r
1803 // セキュアデバイスのモジュールをアンロードする\r
1804 void FreeSecModule(SECURE *sec)\r
1805 {\r
1806         // 引数チェック\r
1807         if (sec == NULL)\r
1808         {\r
1809                 return;\r
1810         }\r
1811 \r
1812         if (sec->Initialized)\r
1813         {\r
1814                 // 初期化済みなので解放する\r
1815                 sec->Api->C_Finalize(NULL);\r
1816                 sec->Initialized = false;\r
1817         }\r
1818 \r
1819 #ifdef  OS_WIN32\r
1820         Win32FreeSecModule(sec);\r
1821 #endif  // OS_WIN32\r
1822 \r
1823 }\r
1824 \r
1825 \r
1826 // セキュアデバイスを取得する\r
1827 SECURE_DEVICE *GetSecureDevice(UINT id)\r
1828 {\r
1829         UINT i;\r
1830 \r
1831         if (id == 0)\r
1832         {\r
1833                 return NULL;\r
1834         }\r
1835 \r
1836         for (i = 0;i < LIST_NUM(SecureDeviceList);i++)\r
1837         {\r
1838                 SECURE_DEVICE *dev = LIST_DATA(SecureDeviceList, i);\r
1839 \r
1840                 if (dev->Id == id)\r
1841                 {\r
1842                         return dev;\r
1843                 }\r
1844         }\r
1845 \r
1846         return NULL;\r
1847 }\r
1848 \r
1849 // セキュアデバイスの ID を確認する\r
1850 bool CheckSecureDeviceId(UINT id)\r
1851 {\r
1852         UINT i;\r
1853 \r
1854         for (i = 0;i < LIST_NUM(SecureDeviceList);i++)\r
1855         {\r
1856                 SECURE_DEVICE *dev = LIST_DATA(SecureDeviceList, i);\r
1857 \r
1858                 if (dev->Id == id)\r
1859                 {\r
1860                         return true;\r
1861                 }\r
1862         }\r
1863 \r
1864         return false;\r
1865 }\r
1866 \r
1867 // サポートされているデバイスリストを取得する\r
1868 LIST *GetSecureDeviceList()\r
1869 {\r
1870         return GetSupportedDeviceList();\r
1871 }\r
1872 \r
1873 // サポートされているデバイスリストを取得する\r
1874 LIST *GetSupportedDeviceList()\r
1875 {\r
1876         // 参照カウントの増加\r
1877         AddRef(SecureDeviceList->ref);\r
1878 \r
1879         return SecureDeviceList;\r
1880 }\r
1881 \r
1882 // 指定したデバイスがインストールされていて利用可能かどうか調べる\r
1883 bool IsDeviceSupported(SECURE_DEVICE *dev)\r
1884 {\r
1885         bool b = false;\r
1886 #ifdef  OS_WIN32\r
1887         b = Win32IsDeviceSupported(dev);\r
1888 #endif  // OS_WIN32\r
1889         return b;\r
1890 }\r
1891 \r
1892 // セキュアデバイスリストの初期化\r
1893 void InitSecureDeviceList()\r
1894 {\r
1895         UINT i, num_supported_list;\r
1896         SecureDeviceList = NewList(NULL);\r
1897 \r
1898         num_supported_list = sizeof(SupportedList) / sizeof(SECURE_DEVICE);\r
1899         for (i = 0; i < num_supported_list;i++)\r
1900         {\r
1901                 SECURE_DEVICE *dev = &SupportedList[i];\r
1902 \r
1903                 // サポートチェック\r
1904                 if (IsDeviceSupported(dev))\r
1905                 {\r
1906                         // サポートされているのでリストに追加\r
1907                         Add(SecureDeviceList, dev);\r
1908                 }\r
1909         }\r
1910 }\r
1911 \r
1912 // テストメイン処理\r
1913 void TestSecMain(SECURE *sec)\r
1914 {\r
1915         char *test_str = "SoftEther UT-VPN";\r
1916         K *public_key, *private_key;\r
1917         // 引数チェック\r
1918         if (sec == NULL)\r
1919         {\r
1920                 return;\r
1921         }\r
1922 \r
1923         Print("test_str: \"%s\"\n", test_str);\r
1924 \r
1925         Print("Writing Data...\n");\r
1926         if (WriteSecData(sec, true, "test_str", test_str, StrLen(test_str)) == false)\r
1927         {\r
1928                 Print("WriteSecData() Failed.\n");\r
1929         }\r
1930         else\r
1931         {\r
1932                 char data[MAX_SIZE];\r
1933                 Zero(data, sizeof(data));\r
1934                 Print("Reading Data...\n");\r
1935                 if (ReadSecData(sec, "test_str", data, sizeof(data)) == false)\r
1936                 {\r
1937                         Print("ReadSecData() Failed.\n");\r
1938                 }\r
1939                 else\r
1940                 {\r
1941                         Print("test_str: \"%s\"\n", data);\r
1942                 }\r
1943                 Print("Deleting Data...\n");\r
1944                 DeleteSecData(sec, "test_str");\r
1945         }\r
1946 \r
1947         Print("Generating Key...\n");\r
1948         if (RsaGen(&private_key, &public_key, 1024) == false)\r
1949         {\r
1950                 Print("RsaGen() Failed.\n");\r
1951         }\r
1952         else\r
1953         {\r
1954                 X *cert;\r
1955                 NAME *name;\r
1956                 X_SERIAL *serial;\r
1957                 UINT num = 0x11220000;\r
1958 \r
1959                 Print("Creating Cert...\n");\r
1960                 serial = NewXSerial(&num, sizeof(UINT));\r
1961                 name = NewName(L"Test", L"Test", L"Test", L"JP", L"Test", L"Test");\r
1962                 cert = NewRootX(public_key, private_key, name, 365, NULL);\r
1963                 FreeXSerial(serial);\r
1964                 if (cert == NULL)\r
1965                 {\r
1966                         Print("NewRootX() Failed.\n");\r
1967                 }\r
1968                 else\r
1969                 {\r
1970                         Print("Writing Cert...\n");\r
1971                         DeleteSecData(sec, "test_cer");\r
1972                         if (WriteSecCert(sec, true, "test_cer", cert) == false)\r
1973                         {\r
1974                                 Print("WriteSecCert() Failed.\n");\r
1975                         }\r
1976                         else\r
1977                         {\r
1978                                 X *x;\r
1979                                 Print("Reading Cert...\n");\r
1980                                 x = ReadSecCert(sec, "test_cer");\r
1981                                 if (x == NULL)\r
1982                                 {\r
1983                                         Print("ReadSecCert() Failed.\n");\r
1984                                 }\r
1985                                 else\r
1986                                 {\r
1987                                         Print("Checking two Certs... ");\r
1988                                         if (CompareX(x, cert) == false)\r
1989                                         {\r
1990                                                 Print("[FAILED]\n");\r
1991                                         }\r
1992                                         else\r
1993                                         {\r
1994                                                 Print("Ok.\n");\r
1995                                         }\r
1996                                         FreeX(x);\r
1997                                 }\r
1998                                 if (cert != NULL)\r
1999                                 {\r
2000                                         X *x;\r
2001                                         XToFile(cert, "cert_tmp.cer", true);\r
2002                                         x = FileToX("cert_tmp.cer");\r
2003                                         if (CompareX(x, cert) == false)\r
2004                                         {\r
2005                                                 Print("[FAILED]\n");\r
2006                                         }\r
2007                                         else\r
2008                                         {\r
2009                                                 Print("Ok.\n");\r
2010                                                 Print("Writing Private Key...\n");\r
2011                                                 DeleteSecKey(sec, "test_key");\r
2012                                                 if (WriteSecKey(sec, true, "test_key", private_key) == false)\r
2013                                                 {\r
2014                                                         Print("WriteSecKey() Failed.\n");\r
2015                                                 }\r
2016                                                 else\r
2017                                                 {\r
2018                                                         UCHAR sign_cpu[128];\r
2019                                                         UCHAR sign_sec[128];\r
2020                                                         K *pub = GetKFromX(cert);\r
2021                                                         Print("Ok.\n");\r
2022                                                         Print("Signing Data by CPU...\n");\r
2023                                                         if (RsaSign(sign_cpu, test_str, StrLen(test_str), private_key) == false)\r
2024                                                         {\r
2025                                                                 Print("RsaSign() Failed.\n");\r
2026                                                         }\r
2027                                                         else\r
2028                                                         {\r
2029                                                                 Print("Ok.\n");\r
2030                                                                 Print("sign_cpu: ");\r
2031                                                                 PrintBin(sign_cpu, sizeof(sign_cpu));\r
2032                                                                 Print("Signing Data by %s..\n", sec->Dev->DeviceName);\r
2033                                                                 if (SignSec(sec, "test_key", sign_sec, test_str, StrLen(test_str)) == false)\r
2034                                                                 {\r
2035                                                                         Print("SignSec() Failed.\n");\r
2036                                                                 }\r
2037                                                                 else\r
2038                                                                 {\r
2039                                                                         Print("Ok.\n");\r
2040                                                                         Print("sign_sec: ");\r
2041                                                                         PrintBin(sign_sec, sizeof(sign_sec));\r
2042                                                                         Print("Compare...");\r
2043                                                                         if (Cmp(sign_sec, sign_cpu, sizeof(sign_cpu)) == 0)\r
2044                                                                         {\r
2045                                                                                 Print("Ok.\n");\r
2046                                                                                 Print("Verify...");\r
2047                                                                                 if (RsaVerify(test_str, StrLen(test_str),\r
2048                                                                                         sign_sec, pub) == false)\r
2049                                                                                 {\r
2050                                                                                         Print("[FAILED]\n");\r
2051                                                                                 }\r
2052                                                                                 else\r
2053                                                                                 {\r
2054                                                                                         Print("Ok.\n");\r
2055                                                                                 }\r
2056                                                                         }\r
2057                                                                         else\r
2058                                                                         {\r
2059                                                                                 Print("[DIFFIRENT]\n");\r
2060                                                                         }\r
2061                                                                 }\r
2062                                                         }\r
2063                                                         Print("Deleting test_key...\n");\r
2064 //                                                      DeleteSecKey(sec, "test_key");\r
2065                                                         FreeK(pub);\r
2066                                                 }\r
2067                                         }\r
2068                                         FreeX(x);\r
2069                                 }\r
2070                         }\r
2071                         Print("Deleting Cert..\n");\r
2072 //                      DeleteSecCert(sec, "test_cer");\r
2073                         FreeX(cert);\r
2074                 }\r
2075                 FreeName(name);\r
2076                 FreeK(private_key);\r
2077                 FreeK(public_key);\r
2078         }\r
2079 }\r
2080 \r
2081 // セキュリティデバイスのテスト\r
2082 void TestSec()\r
2083 {\r
2084         UINT i;\r
2085         LIST *secure_device_list;\r
2086         Print("Secure Device Test Program\n"\r
2087                 "Copyright (C) 2004-2010 SoftEther Corporation. All Rights Reserved.\n\n");\r
2088 \r
2089         // セキュアデバイスリストの取得\r
2090         secure_device_list = GetSecureDeviceList();\r
2091         if (secure_device_list != NULL)\r
2092         {\r
2093                 UINT use_device_id;\r
2094                 char tmp[MAX_SIZE];\r
2095                 Print("--- Secure Device List ---\n");\r
2096                 for (i = 0;i < LIST_NUM(secure_device_list);i++)\r
2097                 {\r
2098                         SECURE_DEVICE *dev = LIST_DATA(secure_device_list, i);\r
2099                         Print("%2u - %s\n", dev->Id, dev->DeviceName);\r
2100                 }\r
2101                 Print("\n");\r
2102                 Print("Device ID >");\r
2103                 GetLine(tmp, sizeof(tmp));\r
2104                 use_device_id = ToInt(tmp);\r
2105                 if (use_device_id == 0)\r
2106                 {\r
2107                         Print("Canceled.\n");\r
2108                 }\r
2109                 else\r
2110                 {\r
2111                         SECURE *sec = OpenSec(use_device_id);\r
2112                         Print("Opening Device...\n");\r
2113                         if (sec == NULL)\r
2114                         {\r
2115                                 Print("OpenSec() Failed.\n");\r
2116                         }\r
2117                         else\r
2118                         {\r
2119                                 Print("Opening Session...\n");\r
2120                                 if (OpenSecSession(sec, 0) == false)\r
2121                                 {\r
2122                                         Print("OpenSecSession() Failed.\n");\r
2123                                 }\r
2124                                 else\r
2125                                 {\r
2126                                         while (true)\r
2127                                         {\r
2128                                                 char pin[MAX_SIZE];\r
2129                                                 Print("PIN Code >");\r
2130                                                 GetLine(pin, sizeof(pin));\r
2131                                                 Trim(pin);\r
2132                                                 if (StrLen(pin) == 0)\r
2133                                                 {\r
2134                                                         Print("Canceled.\n");\r
2135                                                         break;\r
2136                                                 }\r
2137                                                 else\r
2138                                                 {\r
2139                                                         Print("Login...\n");\r
2140                                                         if (LoginSec(sec, pin))\r
2141                                                         {\r
2142                                                                 TestSecMain(sec);\r
2143                                                                 Print("Logout...\n");\r
2144                                                                 LogoutSec(sec);\r
2145                                                                 break;\r
2146                                                         }\r
2147                                                         else\r
2148                                                         {\r
2149                                                                 Print("Login Failed. Please Try Again.\n");\r
2150                                                         }\r
2151                                                 }\r
2152                                         }\r
2153                                         Print("Closing Session...\n");\r
2154                                         CloseSecSession(sec);\r
2155                                 }\r
2156                                 Print("Closing Device...\n");\r
2157                                 CloseSec(sec);\r
2158                         }\r
2159                 }\r
2160                 ReleaseList(secure_device_list);\r
2161         }\r
2162         else\r
2163         {\r
2164                 Print("GetSecureDeviceList() Error.\n");\r
2165         }\r
2166 }\r
2167 \r
2168 // セキュアデバイスリストの解放\r
2169 void FreeSecureDeviceList()\r
2170 {\r
2171         ReleaseList(SecureDeviceList);\r
2172 }\r
2173 \r
2174 // セキュリティトークンモジュールの初期化\r
2175 void InitSecure()\r
2176 {\r
2177         // セキュアデバイスリストの初期化\r
2178         InitSecureDeviceList();\r
2179 }\r
2180 \r
2181 // セキュリティトークンモジュールの解放\r
2182 void FreeSecure()\r
2183 {\r
2184         // セキュアデバイスリストの解放\r
2185         FreeSecureDeviceList();\r
2186 }\r
2187 \r
2188 \r