1 // SoftEther UT-VPN SourceCode
\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
8 // http://utvpn.tsukuba.ac.jp/
\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
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
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
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\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
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
83 #define __WINCRYPT_H__
\r
92 #include <openssl/ssl.h>
\r
93 #include <openssl/err.h>
\r
94 #include <openssl/rand.h>
\r
95 #include <openssl/engine.h>
\r
96 #include <openssl/bio.h>
\r
97 #include <openssl/x509.h>
\r
98 #include <openssl/pkcs7.h>
\r
99 #include <openssl/pkcs12.h>
\r
100 #include <openssl/rc4.h>
\r
101 #include <openssl/md5.h>
\r
102 #include <openssl/sha.h>
\r
103 #include <Mayaqua/Mayaqua.h>
\r
105 LOCK *openssl_lock = NULL;
\r
107 LOCK **ssl_lock_obj = NULL;
\r
109 static bool openssl_inited = false;
\r
112 typedef struct CB_PARAM
\r
117 // 証明書が特定のディレクトリの CRL によって無効化されているかどうか確認する
\r
118 bool IsXRevoked(X *x)
\r
120 char dirname[MAX_PATH];
\r
130 GetExeDir(dirname, sizeof(dirname));
\r
133 t = EnumDir(dirname);
\r
135 for (i = 0;i < t->NumFiles;i++)
\r
137 char *name = t->File[i]->FileName;
\r
138 if (t->File[i]->Folder == false)
\r
140 if (EndWith(name, ".crl"))
\r
142 char filename[MAX_PATH];
\r
145 ConbinePath(filename, sizeof(filename), dirname, name);
\r
147 r = FileToXCrl(filename);
\r
151 if (IsXRevokedByXCrl(x, r))
\r
167 // 証明書が CRL によって無効化されているかどうか確認する
\r
168 bool IsXRevokedByXCrl(X *x, X_CRL *r)
\r
172 X509_CRL_INFO *info;
\r
175 if (x == NULL || r == NULL)
\r
180 Zero(&tmp, sizeof(tmp));
\r
181 tmp.serialNumber = X509_get_serialNumber(x->x509);
\r
183 info = r->Crl->crl;
\r
185 if (sk_X509_REVOKED_is_sorted(info->revoked) == false)
\r
187 sk_X509_REVOKED_sort(info->revoked);
\r
190 index = sk_X509_REVOKED_find(info->revoked, &tmp);
\r
206 void FreeXCrl(X_CRL *r)
\r
214 X509_CRL_free(r->Crl);
\r
220 X_CRL *FileToXCrl(char *filename)
\r
222 wchar_t *filename_w = CopyStrToUni(filename);
\r
223 X_CRL *ret = FileToXCrlW(filename_w);
\r
229 X_CRL *FileToXCrlW(wchar_t *filename)
\r
234 if (filename == NULL)
\r
239 b = ReadDumpW(filename);
\r
253 X_CRL *BufToXCrl(BUF *b)
\r
272 if (d2i_X509_CRL_bio(bio, &x509crl) == NULL || x509crl == NULL)
\r
278 r = ZeroMalloc(sizeof(X_CRL));
\r
287 K *RsaBinToPublic(void *data, UINT size)
\r
293 if (data == NULL || size < 4)
\r
300 if (rsa->e != NULL)
\r
306 BN_set_word(rsa->e, RSA_F4);
\r
308 if (rsa->n != NULL)
\r
313 rsa->n = BinToBigNum(data, size);
\r
316 Lock(openssl_lock);
\r
318 i2d_RSA_PUBKEY_bio(bio, rsa);
\r
320 Unlock(openssl_lock);
\r
322 k = BioToK(bio, false, false, NULL);
\r
331 BUF *RsaPublicToBuf(K *k)
\r
335 if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
\r
336 || k->pkey->pkey.rsa->n == NULL)
\r
341 b = BigNumToBuf(k->pkey->pkey.rsa->n);
\r
351 void RsaPublicToBin(K *k, void *data)
\r
355 if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
\r
356 || k->pkey->pkey.rsa->n == NULL || data == NULL)
\r
361 b = BigNumToBuf(k->pkey->pkey.rsa->n);
\r
367 Copy(data, b->Buf, b->Size);
\r
373 UINT RsaPublicSize(K *k)
\r
378 if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
\r
379 || k->pkey->pkey.rsa->n == NULL)
\r
384 b = BigNumToBuf(k->pkey->pkey.rsa->n);
\r
397 // ポインタを 32 ビットにハッシュする
\r
398 UINT HashPtrToUINT(void *p)
\r
400 UCHAR hash_data[MD5_SIZE];
\r
408 Hash(hash_data, &p, sizeof(p), false);
\r
410 Copy(&ret, hash_data, sizeof(ret));
\r
416 NAME *CopyName(NAME *n)
\r
424 return NewName(n->CommonName, n->Organization, n->Unit,
\r
425 n->Country, n->State, n->Local);
\r
428 // バイナリを BIGNUM に変換
\r
429 BIGNUM *BinToBigNum(void *data, UINT size)
\r
439 BN_bin2bn(data, size, bn);
\r
444 // バッファを BIGNUM に変換
\r
445 BIGNUM *BufToBigNum(BUF *b)
\r
452 return BinToBigNum(b->Buf, b->Size);
\r
456 BUF *BigNumToBuf(BIGNUM *bn)
\r
467 size = BN_num_bytes(bn);
\r
468 tmp = ZeroMalloc(size);
\r
469 BN_bn2bin(bn, tmp);
\r
472 WriteBuf(b, tmp, size);
\r
480 // OpenSSL のロックの初期化
\r
481 void OpenSSL_InitLock()
\r
486 ssl_lock_num = CRYPTO_num_locks();
\r
487 ssl_lock_obj = Malloc(sizeof(LOCK *) * ssl_lock_num);
\r
488 for (i = 0;i < ssl_lock_num;i++)
\r
490 ssl_lock_obj[i] = NewLock();
\r
494 CRYPTO_set_locking_callback(OpenSSL_Lock);
\r
495 CRYPTO_set_id_callback(OpenSSL_Id);
\r
499 void OpenSSL_FreeLock()
\r
503 for (i = 0;i < ssl_lock_num;i++)
\r
505 DeleteLock(ssl_lock_obj[i]);
\r
507 Free(ssl_lock_obj);
\r
508 ssl_lock_obj = NULL;
\r
510 CRYPTO_set_locking_callback(NULL);
\r
511 CRYPTO_set_id_callback(NULL);
\r
515 void OpenSSL_Lock(int mode, int n, const char *file, int line)
\r
517 LOCK *lock = ssl_lock_obj[n];
\r
519 if (mode & CRYPTO_LOCK)
\r
532 unsigned long OpenSSL_Id(void)
\r
534 return (unsigned long)ThreadId();
\r
538 void GetPrintNameFromX(wchar_t *str, UINT size, X *x)
\r
541 if (x == NULL || str == NULL)
\r
546 GetPrintNameFromName(str, size, x->subject_name);
\r
548 void GetPrintNameFromXA(char *str, UINT size, X *x)
\r
550 wchar_t tmp[MAX_SIZE];
\r
552 if (str == NULL || x == NULL)
\r
557 GetPrintNameFromX(tmp, sizeof(tmp), x);
\r
559 UniToStr(str, size, tmp);
\r
561 void GetAllNameFromXEx(wchar_t *str, UINT size, X *x)
\r
564 if (x == NULL || str == NULL)
\r
569 GetAllNameFromNameEx(str, size, x->subject_name);
\r
571 void GetAllNameFromXExA(char *str, UINT size, X *x)
\r
573 wchar_t tmp[MAX_SIZE];
\r
575 if (str == NULL || x == NULL)
\r
580 GetAllNameFromXEx(tmp, sizeof(tmp), x);
\r
582 UniToStr(str, size, tmp);
\r
586 void GetPrintNameFromName(wchar_t *str, UINT size, NAME *name)
\r
589 if (str == NULL || name == NULL)
\r
594 if (name->CommonName != NULL)
\r
596 UniStrCpy(str, size, name->CommonName);
\r
598 else if (name->Organization != NULL)
\r
600 UniStrCpy(str, size, name->Organization);
\r
602 else if (name->Unit != NULL)
\r
604 UniStrCpy(str, size, name->Unit);
\r
606 else if (name->State != NULL)
\r
608 UniStrCpy(str, size, name->State);
\r
610 else if (name->Local != NULL)
\r
612 UniStrCpy(str, size, name->Local);
\r
614 else if (name->Country != NULL)
\r
616 UniStrCpy(str, size, name->Country);
\r
620 UniStrCpy(str, size, L"untitled");
\r
624 // 証明書からすべての名前文字列を取得
\r
625 void GetAllNameFromX(wchar_t *str, UINT size, X *x)
\r
627 UCHAR md5[MD5_SIZE], sha1[SHA1_SIZE];
\r
628 char tmp1[MD5_SIZE * 3 + 8], tmp2[SHA1_SIZE * 3 + 8];
\r
629 wchar_t tmp3[sizeof(tmp1) + sizeof(tmp2) + 64];
\r
631 if (str == NULL || x == NULL)
\r
636 GetAllNameFromName(str, size, x->subject_name);
\r
638 if (x->serial != NULL && x->serial->size >= 1)
\r
643 BinToStr(tmp, sizeof(tmp), x->serial->data, x->serial->size);
\r
644 UniFormat(tmp2, sizeof(tmp2), L", SERIAL=\"%S\"", tmp);
\r
646 UniStrCat(str, size, tmp2);
\r
650 GetXDigest(x, md5, false);
\r
651 GetXDigest(x, sha1, true);
\r
653 BinToStr(tmp1, sizeof(tmp1), md5, MD5_SIZE);
\r
654 BinToStr(tmp2, sizeof(tmp2), sha1, SHA1_SIZE);
\r
656 UniFormat(tmp3, sizeof(tmp3), L" (Digest: MD5=\"%S\", SHA1=\"%S\")", tmp1, tmp2);
\r
657 UniStrCat(str, size, tmp3);
\r
659 void GetAllNameFromA(char *str, UINT size, X *x)
\r
661 wchar_t tmp[MAX_SIZE];
\r
663 if (str == NULL || x == NULL)
\r
668 GetAllNameFromX(tmp, sizeof(tmp), x);
\r
669 UniToStr(str, size, tmp);
\r
672 // NAME からすべての名前文字列を取得
\r
673 void GetAllNameFromName(wchar_t *str, UINT size, NAME *name)
\r
676 if (str == NULL || name == NULL)
\r
681 UniStrCpy(str, size, L"");
\r
682 if (name->CommonName != NULL)
\r
684 UniFormat(str, size, L"%sCN=%s, ", str, name->CommonName);
\r
686 if (name->Organization != NULL)
\r
688 UniFormat(str, size, L"%sO=%s, ", str, name->Organization);
\r
690 if (name->Unit != NULL)
\r
692 UniFormat(str, size, L"%sOU=%s, ", str, name->Unit);
\r
694 if (name->State != NULL)
\r
696 UniFormat(str, size, L"%sS=%s, ", str, name->State);
\r
698 if (name->Local != NULL)
\r
700 UniFormat(str, size, L"%sL=%s, ", str, name->Local);
\r
702 if (name->Country != NULL)
\r
704 UniFormat(str, size, L"%sC=%s, ", str, name->Country);
\r
707 if (UniStrLen(str) >= 3)
\r
709 UINT len = UniStrLen(str);
\r
710 if (str[len - 2] == L',' &&
\r
711 str[len - 1] == L' ')
\r
717 void GetAllNameFromNameEx(wchar_t *str, UINT size, NAME *name)
\r
720 if (str == NULL || name == NULL)
\r
725 UniStrCpy(str, size, L"");
\r
726 if (name->CommonName != NULL)
\r
728 UniFormat(str, size, L"%s%s, ", str, name->CommonName);
\r
730 if (name->Organization != NULL)
\r
732 UniFormat(str, size, L"%s%s, ", str, name->Organization);
\r
734 if (name->Unit != NULL)
\r
736 UniFormat(str, size, L"%s%s, ", str, name->Unit);
\r
738 if (name->State != NULL)
\r
740 UniFormat(str, size, L"%s%s, ", str, name->State);
\r
742 if (name->Local != NULL)
\r
744 UniFormat(str, size, L"%s%s, ", str, name->Local);
\r
746 if (name->Country != NULL)
\r
748 UniFormat(str, size, L"%s%s, ", str, name->Country);
\r
751 if (UniStrLen(str) >= 3)
\r
753 UINT len = UniStrLen(str);
\r
754 if (str[len - 2] == L',' &&
\r
755 str[len - 1] == L' ')
\r
773 b = KToBuf(k, false, NULL);
\r
779 ret = BufToK(b, k->private_key, false, NULL);
\r
796 b = XToBuf(x, false);
\r
802 ret = BufToX(b, false);
\r
809 P12 *NewP12(X *x, K *k, char *password)
\r
814 if (x == NULL || k == NULL)
\r
818 if (password && StrLen(password) == 0)
\r
823 Lock(openssl_lock);
\r
825 pkcs12 = PKCS12_create(password, NULL, k->pkey, x->x509, NULL, 0, 0, 0, 0, 0);
\r
826 if (pkcs12 == NULL)
\r
828 Unlock(openssl_lock);
\r
832 Unlock(openssl_lock);
\r
834 p12 = PKCS12ToP12(pkcs12);
\r
839 // P12 が暗号化されているかどうかチェックする
\r
840 bool IsEncryptedP12(P12 *p12)
\r
850 if (ParseP12(p12, &x, &k, NULL) == true)
\r
860 // P12 から X と K を取り出す
\r
861 bool ParseP12(P12 *p12, X **x, K **k, char *password)
\r
866 if (p12 == NULL || x == NULL || k == NULL)
\r
870 if (password && StrLen(password) == 0)
\r
874 if (password == NULL)
\r
880 Lock(openssl_lock);
\r
882 if (PKCS12_verify_mac(p12->pkcs12, password, -1) == false &&
\r
883 PKCS12_verify_mac(p12->pkcs12, NULL, -1) == false)
\r
885 Unlock(openssl_lock);
\r
889 Unlock(openssl_lock);
\r
892 Lock(openssl_lock);
\r
894 if (PKCS12_parse(p12->pkcs12, password, &pkey, &x509, NULL) == false)
\r
896 if (PKCS12_parse(p12->pkcs12, NULL, &pkey, &x509, NULL) == false)
\r
898 Unlock(openssl_lock);
\r
903 Unlock(openssl_lock);
\r
906 *x = X509ToX(x509);
\r
914 *k = ZeroMalloc(sizeof(K));
\r
915 (*k)->private_key = true;
\r
922 bool P12ToFile(P12 *p12, char *filename)
\r
924 wchar_t *filename_w = CopyStrToUni(filename);
\r
925 bool ret = P12ToFileW(p12, filename_w);
\r
929 bool P12ToFileW(P12 *p12, wchar_t *filename)
\r
933 if (p12 == NULL || filename == NULL)
\r
944 if (DumpBufW(b, filename) == false)
\r
955 // ファイルから P12 を読み込む
\r
956 P12 *FileToP12(char *filename)
\r
958 wchar_t *filename_w = CopyStrToUni(filename);
\r
959 P12 *ret = FileToP12W(filename_w);
\r
965 P12 *FileToP12W(wchar_t *filename)
\r
970 if (filename == NULL)
\r
975 b = ReadDumpW(filename);
\r
988 void FreeP12(P12 *p12)
\r
996 FreePKCS12(p12->pkcs12);
\r
1001 void FreePKCS12(PKCS12 *pkcs12)
\r
1004 if (pkcs12 == NULL)
\r
1009 PKCS12_free(pkcs12);
\r
1012 // P12 を BUF に変換する
\r
1013 BUF *P12ToBuf(P12 *p12)
\r
1023 bio = P12ToBio(p12);
\r
1029 buf = BioToBuf(bio);
\r
1032 SeekBuf(buf, 0, 0);
\r
1037 // P12 を BIO に変換する
\r
1038 BIO *P12ToBio(P12 *p12)
\r
1048 Lock(openssl_lock);
\r
1050 i2d_PKCS12_bio(bio, p12->pkcs12);
\r
1052 Unlock(openssl_lock);
\r
1057 // BUF から P12 を読み込む
\r
1058 P12 *BufToP12(BUF *b)
\r
1068 bio = BufToBio(b);
\r
1074 p12 = BioToP12(bio);
\r
1080 // BIO から P12 を読み込む
\r
1081 P12 *BioToP12(BIO *bio)
\r
1091 Lock(openssl_lock);
\r
1093 pkcs12 = d2i_PKCS12_bio(bio, NULL);
\r
1095 Unlock(openssl_lock);
\r
1096 if (pkcs12 == NULL)
\r
1102 return PKCS12ToP12(pkcs12);
\r
1105 // PKCS12 から P12 を生成する
\r
1106 P12 *PKCS12ToP12(PKCS12 *pkcs12)
\r
1110 if (pkcs12 == NULL)
\r
1115 p12 = ZeroMalloc(sizeof(P12));
\r
1116 p12->pkcs12 = pkcs12;
\r
1122 char *ByteToStr(BYTE *src, UINT src_size)
\r
1133 size = MAX(src_size * 3, 1);
\r
1134 dst = Malloc(size);
\r
1135 dst[size - 1] = 0;
\r
1136 for (i = 0;i < src_size;i++)
\r
1139 Format(tmp, sizeof(tmp), "%02x", src[i]);
\r
1140 dst[i * 3 + 0] = tmp[0];
\r
1141 dst[i * 3 + 1] = tmp[1];
\r
1142 dst[i * 3 + 2] = ((i == (src_size - 1) ? 0 : ' '));
\r
1149 void FreeXSerial(X_SERIAL *serial)
\r
1152 if (serial == NULL)
\r
1157 Free(serial->data);
\r
1162 bool CompareXSerial(X_SERIAL *s1, X_SERIAL *s2)
\r
1165 if (s1 == NULL || s2 == NULL)
\r
1170 if (s1->size != s2->size)
\r
1175 if (Cmp(s1->data, s2->data, s1->size) != 0)
\r
1184 X_SERIAL *CloneXSerial(X_SERIAL *src)
\r
1193 s = ZeroMalloc(sizeof(X_SERIAL));
\r
1194 s->data = ZeroMalloc(src->size);
\r
1195 Copy(s->data, src->data, src->size);
\r
1196 s->size = src->size;
\r
1202 X_SERIAL *NewXSerial(void *data, UINT size)
\r
1205 UCHAR *buf = (UCHAR *)data;
\r
1208 if (data == NULL || size == 0)
\r
1213 for (i = 0;i < size;i++)
\r
1226 serial = Malloc(sizeof(X_SERIAL));
\r
1227 serial->size = size - i;
\r
1228 serial->data = ZeroMalloc(size + 16);
\r
1229 Copy(serial->data, buf, size - i);
\r
1234 // 2038 年 1 月 1 日までの日数を取得する
\r
1235 UINT GetDaysUntil2038()
\r
1237 UINT64 now = SystemTime64();
\r
1241 Zero(&st, sizeof(st));
\r
1246 target = SystemToUINT64(&st);
\r
1248 if (now >= target)
\r
1254 return (UINT)((target - now) / (UINT64)(1000 * 60 * 60 * 24));
\r
1259 X *NewX(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
\r
1264 if (pub == NULL || priv == NULL || name == NULL || ca == NULL)
\r
1269 x509 = NewX509(pub, priv, ca, name, days, serial);
\r
1275 x = X509ToX(x509);
\r
1286 X *NewRootX(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
\r
1291 if (pub == NULL || priv == NULL || name == NULL)
\r
1296 x509 = NewRootX509(pub, priv, name, days, serial);
\r
1302 x = X509ToX(x509);
\r
1315 X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
\r
1318 UINT64 notBefore, notAfter;
\r
1319 ASN1_TIME *t1, *t2;
\r
1320 X509_NAME *subject_name, *issuer_name;
\r
1322 if (pub == NULL || name == NULL || ca == NULL)
\r
1326 if (pub->private_key != false)
\r
1330 if (priv->private_key == false)
\r
1335 notBefore = SystemTime64();
\r
1336 notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;
\r
1340 x509 = X509_new();
\r
1347 t1 = X509_get_notBefore(x509);
\r
1348 t2 = X509_get_notAfter(x509);
\r
1349 if (!UINT64ToAsn1Time(t1, notBefore))
\r
1354 if (!UINT64ToAsn1Time(t2, notAfter))
\r
1361 subject_name = NameToX509Name(name);
\r
1362 if (subject_name == NULL)
\r
1367 issuer_name = X509_get_subject_name(ca->x509);
\r
1368 if (issuer_name == NULL)
\r
1370 FreeX509Name(subject_name);
\r
1375 X509_set_issuer_name(x509, issuer_name);
\r
1376 X509_set_subject_name(x509, subject_name);
\r
1378 FreeX509Name(subject_name);
\r
1381 if (serial == NULL)
\r
1384 ASN1_INTEGER *s = x509->cert_info->serialNumber;
\r
1385 OPENSSL_free(s->data);
\r
1386 s->data = OPENSSL_malloc(sizeof(char));
\r
1387 Copy(s->data, &zero, sizeof(char));
\r
1388 s->length = sizeof(char);
\r
1392 ASN1_INTEGER *s = x509->cert_info->serialNumber;
\r
1393 OPENSSL_free(s->data);
\r
1394 s->data = OPENSSL_malloc(serial->size);
\r
1395 Copy(s->data, serial->data, serial->size);
\r
1396 s->length = serial->size;
\r
1399 Lock(openssl_lock);
\r
1402 X509_set_pubkey(x509, pub->pkey);
\r
1405 X509_sign(x509, priv->pkey, EVP_sha1());
\r
1407 Unlock(openssl_lock);
\r
1412 // ルート X509 証明書を作成する
\r
1413 X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
\r
1416 UINT64 notBefore, notAfter;
\r
1417 ASN1_TIME *t1, *t2;
\r
1418 X509_NAME *subject_name, *issuer_name;
\r
1420 if (pub == NULL || name == NULL || priv == NULL)
\r
1428 if (priv->private_key == false)
\r
1432 if (pub->private_key != false)
\r
1437 notBefore = SystemTime64();
\r
1438 notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;
\r
1441 x509 = X509_new();
\r
1448 t1 = X509_get_notBefore(x509);
\r
1449 t2 = X509_get_notAfter(x509);
\r
1450 if (!UINT64ToAsn1Time(t1, notBefore))
\r
1455 if (!UINT64ToAsn1Time(t2, notAfter))
\r
1462 subject_name = NameToX509Name(name);
\r
1463 if (subject_name == NULL)
\r
1468 issuer_name = NameToX509Name(name);
\r
1469 if (issuer_name == NULL)
\r
1471 FreeX509Name(subject_name);
\r
1476 X509_set_issuer_name(x509, issuer_name);
\r
1477 X509_set_subject_name(x509, subject_name);
\r
1479 FreeX509Name(subject_name);
\r
1480 FreeX509Name(issuer_name);
\r
1483 if (serial == NULL)
\r
1486 ASN1_INTEGER *s = x509->cert_info->serialNumber;
\r
1487 OPENSSL_free(s->data);
\r
1488 s->data = OPENSSL_malloc(sizeof(char));
\r
1489 Copy(s->data, &zero, sizeof(char));
\r
1490 s->length = sizeof(char);
\r
1494 ASN1_INTEGER *s = x509->cert_info->serialNumber;
\r
1495 OPENSSL_free(s->data);
\r
1496 s->data = OPENSSL_malloc(serial->size);
\r
1497 Copy(s->data, serial->data, serial->size);
\r
1498 s->length = serial->size;
\r
1501 Lock(openssl_lock);
\r
1504 X509_set_pubkey(x509, pub->pkey);
\r
1507 X509_sign(x509, priv->pkey, EVP_sha1());
\r
1509 Unlock(openssl_lock);
\r
1514 // NAME を X509_NAME に変換
\r
1515 void *NameToX509Name(NAME *nm)
\r
1524 xn = X509_NAME_new();
\r
1531 AddX509Name(xn, NID_commonName, nm->CommonName);
\r
1532 AddX509Name(xn, NID_organizationName, nm->Organization);
\r
1533 AddX509Name(xn, NID_organizationalUnitName, nm->Unit);
\r
1534 AddX509Name(xn, NID_countryName, nm->Country);
\r
1535 AddX509Name(xn, NID_stateOrProvinceName, nm->State);
\r
1536 AddX509Name(xn, NID_localityName, nm->Local);
\r
1541 // X509_NAME にエントリを追加する
\r
1542 bool AddX509Name(void *xn, int nid, wchar_t *str)
\r
1544 X509_NAME *x509_name;
\r
1548 if (xn == NULL || str == NULL)
\r
1554 utf8_size = CalcUniToUtf8(str);
\r
1555 if (utf8_size == 0)
\r
1559 utf8 = ZeroMalloc(utf8_size + 1);
\r
1560 UniToUtf8(utf8, utf8_size, str);
\r
1561 utf8[utf8_size] = 0;
\r
1564 x509_name = (X509_NAME *)xn;
\r
1565 Lock(openssl_lock);
\r
1567 X509_NAME_add_entry_by_NID(x509_name, nid, MBSTRING_ASC, utf8, utf8_size, -1, 0);
\r
1569 Unlock(openssl_lock);
\r
1576 void FreeX509Name(void *xn)
\r
1578 X509_NAME *x509_name;
\r
1585 x509_name = (X509_NAME *)xn;
\r
1586 X509_NAME_free(x509_name);
\r
1590 NAME *NewName(wchar_t *common_name, wchar_t *organization, wchar_t *unit,
\r
1591 wchar_t *country, wchar_t *state, wchar_t *local)
\r
1593 NAME *nm = ZeroMalloc(sizeof(NAME));
\r
1595 if (UniIsEmptyStr(common_name) == false)
\r
1597 nm->CommonName = CopyUniStr(common_name);
\r
1600 if (UniIsEmptyStr(organization) == false)
\r
1602 nm->Organization = CopyUniStr(organization);
\r
1605 if (UniIsEmptyStr(unit) == false)
\r
1607 nm->Unit = CopyUniStr(unit);
\r
1610 if (UniIsEmptyStr(country) == false)
\r
1612 nm->Country = CopyUniStr(country);
\r
1615 if (UniIsEmptyStr(state) == false)
\r
1617 nm->State = CopyUniStr(state);
\r
1620 if (UniIsEmptyStr(local) == false)
\r
1622 nm->Local = CopyUniStr(local);
\r
1628 // 証明書の有効期限を現在時刻で確認する
\r
1629 bool CheckXDateNow(X *x)
\r
1637 return CheckXDate(x, SystemTime64());
\r
1641 bool CheckXDate(X *x, UINT64 current_system_time)
\r
1649 if (x->notBefore >= current_system_time || x->notAfter <= current_system_time)
\r
1656 // 証明書の有効期限情報を読み込む
\r
1657 void LoadXDates(X *x)
\r
1665 x->notBefore = Asn1TimeToUINT64(x->x509->cert_info->validity->notBefore);
\r
1666 x->notAfter = Asn1TimeToUINT64(x->x509->cert_info->validity->notAfter);
\r
1669 // 64bit システム時刻を ASN1 時刻に変換する
\r
1670 bool UINT64ToAsn1Time(void *asn1_time, UINT64 t)
\r
1674 if (asn1_time == NULL)
\r
1679 UINT64ToSystem(&st, t);
\r
1680 return SystemToAsn1Time(asn1_time, &st);
\r
1683 // システム時刻を ASN1 時刻に変換する
\r
1684 bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s)
\r
1689 if (asn1_time == NULL || s == NULL)
\r
1694 if (SystemToStr(tmp, sizeof(tmp), s) == false)
\r
1698 t = (ASN1_TIME *)asn1_time;
\r
1699 if (t->data == NULL || t->length < sizeof(tmp))
\r
1701 t->data = OPENSSL_malloc(sizeof(tmp));
\r
1703 StrCpy((char *)t->data, t->length, tmp);
\r
1704 t->length = StrLen(tmp);
\r
1705 t->type = V_ASN1_UTCTIME;
\r
1710 // システム時刻を文字列に変換する
\r
1711 bool SystemToStr(char *str, UINT size, SYSTEMTIME *s)
\r
1714 if (str == NULL || s == NULL)
\r
1719 Format(str, size, "%02u%02u%02u%02u%02u%02uZ",
\r
1720 s->wYear % 100, s->wMonth, s->wDay,
\r
1721 s->wHour, s->wMinute, s->wSecond);
\r
1726 // ASN1 時刻を UINT64 時刻に変換する
\r
1727 UINT64 Asn1TimeToUINT64(void *asn1_time)
\r
1731 if (asn1_time == NULL)
\r
1736 if (Asn1TimeToSystem(&st, asn1_time) == false)
\r
1740 return SystemToUINT64(&st);
\r
1743 // ASN1 時刻をシステム時刻に変換する
\r
1744 bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time)
\r
1748 if (s == NULL || asn1_time == NULL)
\r
1753 t = (ASN1_TIME *)asn1_time;
\r
1754 if (StrToSystem(s, (char *)t->data) == false)
\r
1759 if (t->type == V_ASN1_GENERALIZEDTIME)
\r
1761 LocalToSystem(s, s);
\r
1767 // 文字列をシステム時刻に変換する
\r
1768 bool StrToSystem(SYSTEMTIME *s, char *str)
\r
1771 if (s == NULL || str == NULL)
\r
1775 if (StrLen(str) != 13)
\r
1779 if (str[12] != 'Z')
\r
1786 char year[3] = {str[0], str[1], 0},
\r
1787 month[3] = {str[2], str[3], 0},
\r
1788 day[3] = {str[4], str[5], 0},
\r
1789 hour[3] = {str[6], str[7], 0},
\r
1790 minute[3] = {str[8], str[9], 0},
\r
1791 second[3] = {str[10], str[11], 0};
\r
1792 Zero(s, sizeof(SYSTEMTIME));
\r
1793 s->wYear = ToInt(year);
\r
1794 if (s->wYear >= 60)
\r
1802 s->wMonth = ToInt(month);
\r
1803 s->wDay = ToInt(day);
\r
1804 s->wHour = ToInt(hour);
\r
1805 s->wMinute = ToInt(minute);
\r
1806 s->wSecond = ToInt(second);
\r
1807 NormalizeSystem(s);
\r
1814 bool RsaVerify(void *data, UINT data_size, void *sign, K *k)
\r
1816 return RsaVerifyEx(data, data_size, sign, k, 0);
\r
1818 bool RsaVerifyEx(void *data, UINT data_size, void *sign, K *k, UINT bits)
\r
1820 UCHAR hash_data[SIGN_HASH_SIZE];
\r
1821 UCHAR decrypt_data[SIGN_HASH_SIZE];
\r
1823 if (data == NULL || sign == NULL || k == NULL || k->private_key != false)
\r
1833 if (HashForSign(hash_data, sizeof(hash_data), data, data_size) == false)
\r
1839 if (RSA_public_decrypt(bits / 8, sign, decrypt_data, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)
\r
1845 if (Cmp(decrypt_data, hash_data, sizeof(SIGN_HASH_SIZE)) != 0)
\r
1854 bool RsaSign(void *dst, void *src, UINT size, K *k)
\r
1856 return RsaSignEx(dst, src, size, k, 0);
\r
1858 bool RsaSignEx(void *dst, void *src, UINT size, K *k, UINT bits)
\r
1860 UCHAR hash[SIGN_HASH_SIZE];
\r
1862 if (dst == NULL || src == NULL || k == NULL || k->pkey->type != EVP_PKEY_RSA)
\r
1871 Zero(dst, bits / 8);
\r
1874 if (HashForSign(hash, sizeof(hash), src, size) == false)
\r
1880 if (RSA_private_encrypt(sizeof(hash), hash, dst, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)
\r
1888 // SHA-1 による署名データの生成
\r
1889 bool HashForSign(void *dst, UINT dst_size, void *src, UINT src_size)
\r
1891 UCHAR *buf = (UCHAR *)dst;
\r
1892 UCHAR sign_data[] =
\r
1894 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E,
\r
1895 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
\r
1898 if (dst == NULL || src == NULL || src_size == 0 || MIN_SIGN_HASH_SIZE > dst_size)
\r
1904 Copy(buf, sign_data, sizeof(sign_data));
\r
1907 HashSha1(HASHED_DATA(buf), src, src_size);
\r
1913 bool RsaPublicDecrypt(void *dst, void *src, UINT size, K *k)
\r
1918 if (src == NULL || size == 0 || k == NULL)
\r
1923 tmp = ZeroMalloc(size);
\r
1924 Lock(openssl_lock);
\r
1926 ret = RSA_public_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
\r
1928 Unlock(openssl_lock);
\r
1931 /* Debug("RSA Error: 0x%x\n",
\r
1937 Copy(dst, tmp, size);
\r
1944 bool RsaPrivateEncrypt(void *dst, void *src, UINT size, K *k)
\r
1949 if (src == NULL || size == 0 || k == NULL)
\r
1954 tmp = ZeroMalloc(size);
\r
1955 Lock(openssl_lock);
\r
1957 ret = RSA_private_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
\r
1959 Unlock(openssl_lock);
\r
1962 /* Debug("RSA Error: %u\n",
\r
1963 ERR_GET_REASON(ERR_get_error()));
\r
1968 Copy(dst, tmp, size);
\r
1975 bool RsaPrivateDecrypt(void *dst, void *src, UINT size, K *k)
\r
1980 if (src == NULL || size == 0 || k == NULL)
\r
1985 tmp = ZeroMalloc(size);
\r
1986 Lock(openssl_lock);
\r
1988 ret = RSA_private_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
\r
1990 Unlock(openssl_lock);
\r
1996 Copy(dst, tmp, size);
\r
2003 bool RsaPublicEncrypt(void *dst, void *src, UINT size, K *k)
\r
2008 if (src == NULL || size == 0 || k == NULL)
\r
2013 tmp = ZeroMalloc(size);
\r
2014 Lock(openssl_lock);
\r
2016 ret = RSA_public_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
\r
2018 Unlock(openssl_lock);
\r
2024 Copy(dst, tmp, size);
\r
2036 for (i = 0;i < num;i++)
\r
2051 K *priv_key, *pub_key;
\r
2053 char errbuf[MAX_SIZE];
\r
2059 Lock(openssl_lock);
\r
2061 rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);
\r
2063 Unlock(openssl_lock);
\r
2066 Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));
\r
2072 Lock(openssl_lock);
\r
2074 i2d_RSAPrivateKey_bio(bio, rsa);
\r
2076 Unlock(openssl_lock);
\r
2078 priv_key = BioToK(bio, true, false, NULL);
\r
2083 Lock(openssl_lock);
\r
2085 i2d_RSA_PUBKEY_bio(bio, rsa);
\r
2087 Unlock(openssl_lock);
\r
2089 pub_key = BioToK(bio, false, false, NULL);
\r
2094 size = RsaPublicSize(pub_key);
\r
2096 if (size != ((bit + 7) / 8))
\r
2111 bool RsaGen(K **priv, K **pub, UINT bit)
\r
2114 K *priv_key, *pub_key;
\r
2116 char errbuf[MAX_SIZE];
\r
2119 if (priv == NULL || pub == NULL)
\r
2129 Lock(openssl_lock);
\r
2131 rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);
\r
2133 Unlock(openssl_lock);
\r
2136 Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));
\r
2142 Lock(openssl_lock);
\r
2144 i2d_RSAPrivateKey_bio(bio, rsa);
\r
2146 Unlock(openssl_lock);
\r
2148 priv_key = BioToK(bio, true, false, NULL);
\r
2153 Lock(openssl_lock);
\r
2155 i2d_RSA_PUBKEY_bio(bio, rsa);
\r
2157 Unlock(openssl_lock);
\r
2159 pub_key = BioToK(bio, false, false, NULL);
\r
2167 size = RsaPublicSize(*pub);
\r
2169 if (size != ((bit + 7) / 8))
\r
2174 return RsaGen(priv, pub, bit);
\r
2180 // 証明書 X が証明書 x_issuer の発行者によって署名されているかどうか確認する
\r
2181 bool CheckX(X *x, X *x_issuer)
\r
2186 if (x == NULL || x_issuer == NULL)
\r
2191 k = GetKFromX(x_issuer);
\r
2197 ret = CheckSignature(x, k);
\r
2203 // 証明書 X の署名を公開鍵 K で確認する
\r
2204 bool CheckSignature(X *x, K *k)
\r
2207 if (x == NULL || k == NULL)
\r
2212 Lock(openssl_lock);
\r
2214 if (X509_verify(x->x509, k->pkey) == 0)
\r
2216 Unlock(openssl_lock);
\r
2220 Unlock(openssl_lock);
\r
2225 K *GetKFromX(X *x)
\r
2235 Lock(openssl_lock);
\r
2237 pkey = X509_get_pubkey(x->x509);
\r
2239 Unlock(openssl_lock);
\r
2245 k = ZeroMalloc(sizeof(K));
\r
2252 bool CompareName(NAME *n1, NAME *n2)
\r
2255 if (n1 == NULL || n2 == NULL)
\r
2261 if (UniStrCmpi(n1->CommonName, n2->CommonName) == 0 &&
\r
2262 UniStrCmpi(n1->Organization, n2->Organization) == 0 &&
\r
2263 UniStrCmpi(n1->Unit, n2->Unit) == 0 &&
\r
2264 UniStrCmpi(n1->Country, n2->Country) == 0 &&
\r
2265 UniStrCmpi(n1->State, n2->State) == 0 &&
\r
2266 UniStrCmpi(n1->Local, n2->Local) == 0)
\r
2275 void FreeXNames(X *x)
\r
2283 FreeName(x->issuer_name);
\r
2284 x->issuer_name = NULL;
\r
2286 FreeName(x->subject_name);
\r
2287 x->subject_name = NULL;
\r
2291 void FreeName(NAME *n)
\r
2300 Free(n->CommonName);
\r
2301 Free(n->Organization);
\r
2314 void LoadXNames(X *x)
\r
2324 x->issuer_name = X509NameToName(X509_get_issuer_name(x509));
\r
2325 x->subject_name = X509NameToName(X509_get_subject_name(x509));
\r
2328 // X509_NAME 構造体を NAME 構造体に変換
\r
2329 NAME *X509NameToName(void *xn)
\r
2338 n = ZeroMalloc(sizeof(NAME));
\r
2341 n->CommonName = GetUniStrFromX509Name(xn, NID_commonName);
\r
2342 n->Organization = GetUniStrFromX509Name(xn, NID_organizationName);
\r
2343 n->Unit = GetUniStrFromX509Name(xn, NID_organizationalUnitName);
\r
2344 n->Country = GetUniStrFromX509Name(xn, NID_countryName);
\r
2345 n->State = GetUniStrFromX509Name(xn, NID_stateOrProvinceName);
\r
2346 n->Local = GetUniStrFromX509Name(xn, NID_localityName);
\r
2351 // X509_NAME 構造体の中から Unicode 文字列を読み込む
\r
2352 wchar_t *GetUniStrFromX509Name(void *xn, int nid)
\r
2358 bool unicode = false;
\r
2359 bool is_utf_8 = false;
\r
2361 ASN1_STRING *data;
\r
2363 if (xn == NULL || nid == 0)
\r
2368 Zero(txt, sizeof(txt));
\r
2369 if (X509_NAME_get_text_by_NID(xn, nid, (char *)txt, sizeof(txt) - 2) <= 0)
\r
2374 obj = OBJ_nid2obj(nid);
\r
2379 index = X509_NAME_get_index_by_OBJ(xn, obj, -1);
\r
2384 data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(xn, index));
\r
2389 if (data->type == V_ASN1_BMPSTRING)
\r
2393 if (data->type == V_ASN1_UTF8STRING || data->type == V_ASN1_T61STRING)
\r
2398 size = UniStrLen((wchar_t *)txt) * 4 + 8;
\r
2399 for (i = 0;i < size;i++)
\r
2401 if (txt[i] >= 0x80)
\r
2413 ret_size = CalcUtf8ToUni(txt, StrLen(txt));
\r
2414 ret = ZeroMalloc(ret_size + 8);
\r
2415 Utf8ToUni(ret, ret_size, txt, StrLen(txt));
\r
2419 else if (unicode == false)
\r
2421 wchar_t tmp[1024];
\r
2422 StrToUni(tmp, sizeof(tmp), (char *)txt);
\r
2423 return CopyUniStr(tmp);
\r
2427 EndianUnicode((wchar_t *)txt);
\r
2428 return CopyUniStr((wchar_t *)txt);
\r
2432 // 証明書 x1 と x2 が等しいかどうかチェックする
\r
2433 bool CompareX(X *x1, X *x2)
\r
2436 if (x1 == NULL || x2 == NULL)
\r
2441 Lock(openssl_lock);
\r
2442 if (X509_cmp(x1->x509, x2->x509) == 0)
\r
2444 Unlock(openssl_lock);
\r
2449 Unlock(openssl_lock);
\r
2454 // K が X の秘密鍵かどうかチェックする
\r
2455 bool CheckXandK(X *x, K *k)
\r
2458 if (x == NULL || k == NULL)
\r
2463 Lock(openssl_lock);
\r
2464 if (X509_check_private_key(x->x509, k->pkey) != 0)
\r
2466 Unlock(openssl_lock);
\r
2471 Unlock(openssl_lock);
\r
2477 X *FileToX(char *filename)
\r
2479 wchar_t *filename_w = CopyStrToUni(filename);
\r
2480 X *ret = FileToXW(filename_w);
\r
2486 X *FileToXW(wchar_t *filename)
\r
2492 if (filename == NULL)
\r
2497 b = ReadDumpW(filename);
\r
2498 text = IsBase64(b);
\r
2500 x = BufToX(b, text);
\r
2507 bool XToFile(X *x, char *filename, bool text)
\r
2509 wchar_t *filename_w = CopyStrToUni(filename);
\r
2510 bool ret = XToFileW(x, filename_w, text);
\r
2516 bool XToFileW(X *x, wchar_t *filename, bool text)
\r
2521 if (x == NULL || filename == NULL)
\r
2526 b = XToBuf(x, text);
\r
2532 ret = DumpBufW(b, filename);
\r
2539 K *FileToK(char *filename, bool private_key, char *password)
\r
2541 wchar_t *filename_w = CopyStrToUni(filename);
\r
2544 ret = FileToKW(filename_w, private_key, password);
\r
2550 K *FileToKW(wchar_t *filename, bool private_key, char *password)
\r
2556 if (filename == NULL)
\r
2561 b = ReadDumpW(filename);
\r
2567 text = IsBase64(b);
\r
2568 if (text == false)
\r
2570 k = BufToK(b, private_key, false, NULL);
\r
2574 k = BufToK(b, private_key, true, NULL);
\r
2577 k = BufToK(b, private_key, true, password);
\r
2587 bool KToFile(K *k, char *filename, bool text, char *password)
\r
2589 wchar_t *filename_w = CopyStrToUni(filename);
\r
2590 bool ret = KToFileW(k, filename_w, text, password);
\r
2596 bool KToFileW(K *k, wchar_t *filename, bool text, char *password)
\r
2601 if (k == NULL || filename == NULL)
\r
2606 b = KToBuf(k, text, password);
\r
2612 ret = DumpBufW(b, filename);
\r
2619 BUF *KToBuf(K *k, bool text, char *password)
\r
2629 bio = KToBio(k, text, password);
\r
2635 buf = BioToBuf(bio);
\r
2638 SeekBuf(buf, 0, 0);
\r
2644 BIO *KToBio(K *k, bool text, char *password)
\r
2655 if (k->private_key)
\r
2658 if (text == false)
\r
2661 Lock(openssl_lock);
\r
2663 i2d_PrivateKey_bio(bio, k->pkey);
\r
2665 Unlock(openssl_lock);
\r
2670 if (password == 0 || StrLen(password) == 0)
\r
2673 Lock(openssl_lock);
\r
2675 PEM_write_bio_PrivateKey(bio, k->pkey, NULL, NULL, 0, NULL, NULL);
\r
2677 Unlock(openssl_lock);
\r
2683 cb.password = password;
\r
2684 Lock(openssl_lock);
\r
2686 PEM_write_bio_PrivateKey(bio, k->pkey, EVP_des_ede3_cbc(),
\r
2687 NULL, 0, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
\r
2689 Unlock(openssl_lock);
\r
2696 if (text == false)
\r
2699 Lock(openssl_lock);
\r
2701 i2d_PUBKEY_bio(bio, k->pkey);
\r
2703 Unlock(openssl_lock);
\r
2708 Lock(openssl_lock);
\r
2710 PEM_write_bio_PUBKEY(bio, k->pkey);
\r
2712 Unlock(openssl_lock);
\r
2719 // BUF が Base64 エンコードされているかどうか調べる
\r
2720 bool IsBase64(BUF *b)
\r
2729 for (i = 0;i < b->Size;i++)
\r
2731 char c = ((char *)b->Buf)[i];
\r
2733 if ('a' <= c && c <= 'z')
\r
2737 else if ('A' <= c && c <= 'Z')
\r
2741 else if ('0' <= c && c <= '9')
\r
2745 else if (c == ':' || c == '.' || c == ';' || c == ',')
\r
2749 else if (c == '!' || c == '&' || c == '#' || c == '(' || c == ')')
\r
2753 else if (c == '-' || c == ' ')
\r
2757 else if (c == 13 || c == 10 || c == EOF)
\r
2761 else if (c == '\t' || c == '=' || c == '+' || c == '/')
\r
2773 // BUF に含まれている K が暗号化されているかどうか調べる
\r
2774 bool IsEncryptedK(BUF *b, bool private_key)
\r
2782 if (IsBase64(b) == false)
\r
2787 k = BufToK(b, private_key, true, NULL);
\r
2798 K *BufToK(BUF *b, bool private_key, bool text, char *password)
\r
2808 bio = BufToBio(b);
\r
2809 k = BioToK(bio, private_key, text, password);
\r
2824 FreePKey(k->pkey);
\r
2829 void FreePKey(EVP_PKEY *pkey)
\r
2837 EVP_PKEY_free(pkey);
\r
2841 K *BioToK(BIO *bio, bool private_key, bool text, char *password)
\r
2851 if (password != NULL && StrLen(password) == 0)
\r
2856 if (private_key == false)
\r
2859 if (text == false)
\r
2862 pkey = d2i_PUBKEY_bio(bio, NULL);
\r
2872 cb.password = password;
\r
2873 Lock(openssl_lock);
\r
2875 pkey = PEM_read_bio_PUBKEY(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
\r
2877 Unlock(openssl_lock);
\r
2886 if (text == false)
\r
2889 Lock(openssl_lock);
\r
2891 pkey = d2i_PrivateKey_bio(bio, NULL);
\r
2893 Unlock(openssl_lock);
\r
2903 cb.password = password;
\r
2904 Lock(openssl_lock);
\r
2906 pkey = PEM_read_bio_PrivateKey(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
\r
2908 Unlock(openssl_lock);
\r
2916 k = ZeroMalloc(sizeof(K));
\r
2918 k->private_key = private_key;
\r
2924 int PKeyPasswordCallbackFunction(char *buf, int bufsize, int verify, void *param)
\r
2928 if (buf == NULL || param == NULL || bufsize == 0)
\r
2933 cb = (CB_PARAM *)param;
\r
2934 if (cb->password == NULL)
\r
2939 return StrCpy(buf, bufsize, cb->password);
\r
2943 BUF *XToBuf(X *x, bool text)
\r
2953 bio = XToBio(x, text);
\r
2959 b = BioToBuf(bio);
\r
2968 BIO *XToBio(X *x, bool text)
\r
2979 Lock(openssl_lock);
\r
2981 if (text == false)
\r
2984 i2d_X509_bio(bio, x->x509);
\r
2989 PEM_write_bio_X509(bio, x->x509);
\r
2992 Unlock(openssl_lock);
\r
3011 FreeXSerial(x->serial);
\r
3013 if (x->do_not_free == false)
\r
3015 FreeX509(x->x509);
\r
3021 void FreeX509(X509 *x509)
\r
3029 Lock(openssl_lock);
\r
3033 Unlock(openssl_lock);
\r
3037 X *BufToX(BUF *b, bool text)
\r
3047 bio = BufToBio(b);
\r
3053 x = BioToX(bio, text);
\r
3061 void GetXDigest(X *x, UCHAR *buf, bool sha1)
\r
3069 if (sha1 == false)
\r
3071 UINT size = MD5_SIZE;
\r
3072 X509_digest(x->x509, EVP_md5(), buf, (unsigned int *)&size);
\r
3076 UINT size = SHA1_SIZE;
\r
3077 X509_digest(x->x509, EVP_sha1(), buf, (unsigned int *)&size);
\r
3082 X *BioToX(BIO *bio, bool text)
\r
3092 Lock(openssl_lock);
\r
3095 if (text == false)
\r
3098 x509 = d2i_X509_bio(bio, NULL);
\r
3103 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
\r
3106 Unlock(openssl_lock);
\r
3113 x = X509ToX(x509);
\r
3124 X *X509ToX(X509 *x509)
\r
3137 x = ZeroMalloc(sizeof(X));
\r
3146 // ルート証明書かどうかチェックする
\r
3147 if (CompareName(x->issuer_name, x->subject_name))
\r
3149 K *pubkey = GetKFromX(x);
\r
3150 if (pubkey != NULL)
\r
3152 if (CheckXandK(x, pubkey))
\r
3154 x->root_cert = true;
\r
3161 x->serial = NewXSerial(x509->cert_info->serialNumber->data,
\r
3162 x509->cert_info->serialNumber->length);
\r
3163 if (x->serial == NULL)
\r
3166 x->serial = NewXSerial(&zero, sizeof(char));
\r
3176 b = KToBuf(k, false, NULL);
\r
3179 type = k->pkey->type;
\r
3185 if (type == EVP_PKEY_RSA)
\r
3187 x->is_compatible_bit = true;
\r
3212 x->is_compatible_bit = false;
\r
3223 return BIO_new(BIO_s_mem());
\r
3227 void FreeBio(BIO *bio)
\r
3238 // BIO を BUF に変換する
\r
3239 BUF *BioToBuf(BIO *bio)
\r
3251 size = bio->num_write;
\r
3252 tmp = Malloc(size);
\r
3253 BIO_read(bio, tmp, size);
\r
3256 WriteBuf(b, tmp, size);
\r
3262 // BUF を BIO に変換する
\r
3263 BIO *BufToBio(BUF *b)
\r
3272 Lock(openssl_lock);
\r
3274 bio = BIO_new(BIO_s_mem());
\r
3277 Unlock(openssl_lock);
\r
3280 BIO_write(bio, b->Buf, b->Size);
\r
3283 Unlock(openssl_lock);
\r
3289 void Rand128(void *buf)
\r
3298 Rand(&i, sizeof(i));
\r
3306 Rand(&i, sizeof(i));
\r
3314 Rand(&i, sizeof(i));
\r
3322 Rand(&i, sizeof(i));
\r
3329 return (Rand32() % 2) == 0 ? false : true;
\r
3333 void Rand(void *buf, UINT size)
\r
3336 if (buf == NULL || size == 0)
\r
3340 RAND_bytes(buf, size);
\r
3343 // OpenSSL が確保しているスレッド固有情報を削除する
\r
3344 void FreeOpenSSLThreadState()
\r
3346 ERR_remove_state(0);
\r
3350 void FreeCryptLibrary()
\r
3352 openssl_inited = false;
\r
3354 DeleteLock(openssl_lock);
\r
3355 openssl_lock = NULL;
\r
3356 // RAND_Free_For_SoftEther();
\r
3357 OpenSSL_FreeLock();
\r
3361 void InitCryptLibrary()
\r
3364 // RAND_Init_For_SoftEther()
\r
3365 openssl_lock = NewLock();
\r
3366 SSL_library_init();
\r
3367 //OpenSSL_add_all_algorithms();
\r
3368 OpenSSL_add_all_ciphers();
\r
3369 SSLeay_add_all_digests();
\r
3370 ERR_load_crypto_strings();
\r
3371 SSL_load_error_strings();
\r
3375 char *name1 = "/dev/random";
\r
3376 char *name2 = "/dev/urandom";
\r
3378 o = FileOpen(name1, false);
\r
3381 o = FileOpen(name2, false);
\r
3384 UINT64 now = SystemTime64();
\r
3388 for (i = 0;i < 4096;i++)
\r
3390 UCHAR c = rand() % 256;
\r
3391 WriteBuf(b, &c, 1);
\r
3393 WriteBuf(b, &now, sizeof(now));
\r
3394 RAND_seed(b->Buf, b->Size);
\r
3414 Rand(tmp, sizeof(tmp));
\r
3415 OpenSSL_InitLock();
\r
3417 openssl_inited = true;
\r
3421 void InternalHash(void *dst, void *src, UINT size, bool sha1)
\r
3424 if (dst == NULL || (src == NULL && size != 0))
\r
3429 if (sha1 == false)
\r
3432 MD5(src, size, dst);
\r
3437 SHA(src, size, dst);
\r
3442 void HashSha1(void *dst, void *src, UINT size)
\r
3444 SHA1(src, size, dst);
\r
3448 void Hash(void *dst, void *src, UINT size, bool sha1)
\r
3450 InternalHash(dst, src, size, sha1);
\r
3453 // 新しい CRYPT オブジェクトの作成
\r
3454 CRYPT *NewCrypt(void *key, UINT size)
\r
3456 CRYPT *c = ZeroMalloc(sizeof(CRYPT));
\r
3458 SetKey(c, key, size);
\r
3463 // CRYPT オブジェクトの解放
\r
3464 void FreeCrypt(CRYPT *c)
\r
3477 void InternalEncrypt(CRYPT *c, void *dst, void *src, UINT size)
\r
3479 UINT x, y, sx, sy;
\r
3482 UCHAR *s = (UCHAR *)src;
\r
3483 UCHAR *d = (UCHAR *)dst;
\r
3485 if (c == NULL || dst == NULL || src == NULL || size == 0)
\r
3490 state = (UINT *)c->state;
\r
3494 for (endsrc = s + size;s != endsrc;s++, d++)
\r
3496 x = (x + 1) & 0xff;
\r
3498 y = (sx + y) & 0xff;
\r
3499 state[x] = sy = state[y];
\r
3501 *d = *s ^ state[(sx + sy) & 0xff];
\r
3506 void Encrypt(CRYPT *c, void *dst, void *src, UINT size)
\r
3508 InternalEncrypt(c, dst, src, size);
\r
3512 void SetKey(CRYPT *c, void *key, UINT size)
\r
3514 UINT i, t, u, ki, si;
\r
3516 UCHAR *k = (UCHAR *)key;
\r
3518 if (c == NULL || key == NULL)
\r
3524 state = (UINT *)c->state;
\r
3526 for (i = 0;i < 256;i++)
\r
3532 for (i = 0;i < 256;i++)
\r
3535 si = (si + k[ki] + t) & 0xff;
\r