source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/Secure.c @ 86521dd

trunk
Last change on this file since 86521dd was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

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