windows-nt/Source/XPSP1/NT/ds/win32/ntcrypto/sgc/sgccheck.c
2020-09-26 16:20:57 +08:00

956 lines
34 KiB
C

/////////////////////////////////////////////////////////////////////////////
// FILE : sgccheck.c //
// DESCRIPTION : Code to check if SGC is enabled //
// AUTHOR : jeffspel //
// HISTORY : //
// Jun 16 1998 jeffspel Create //
// Nov 16 1998 jbanes Pluggable SGC roots. //
// //
// Copyright (C) 1998 Microsoft Corporation All Rights Reserved //
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <windef.h>
#include <wincrypt.h>
#include <sgccheck.h>
#define SGCAlloc(cb) LocalAlloc(LMEM_ZEROINIT, cb)
#define SGCFree(pb) LocalFree(pb)
//#define SGC_TEST_KEY // COMMENT OUT THIS LINE BEFORE CHECKING IN!!!
#ifdef SGC_TEST_KEY
#pragma message ("WARNING -- Building with SGC Test Key enabled.")
#endif
#define SGC_VERIFICATION_FLAGS (CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG)
// Geneva SGC Root
static CONST BYTE GenevaSGCRoot[] =
{ 0x30, 0x82, 0x03, 0x0a, 0x30, 0x82, 0x01, 0xf2, // 0...0...
0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x20, // .......
0x9d, 0x11, 0xd1, 0x0e, 0x7f, 0x7b, 0x85, 0x74, // .....{.t
0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, // .0...*.H
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, // ........
0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, // 0.1.0...
0x55, 0x04, 0x03, 0x13, 0x12, 0x52, 0x6f, 0x6f, // U....Roo
0x74, 0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, // t SGC Au
0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, // thority0
0x1e, 0x17, 0x0d, 0x39, 0x37, 0x30, 0x38, 0x30, // ...97080
0x36, 0x31, 0x37, 0x31, 0x34, 0x34, 0x37, 0x5a, // 6171447Z
0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, // ..100101
0x30, 0x37, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, // 070000Z0
0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, // .1.0...U
0x04, 0x03, 0x13, 0x12, 0x52, 0x6f, 0x6f, 0x74, // ....Root
0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, // hority0.
0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, // ."0...*.
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, // H.......
0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, // ......0.
0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xec, // ........
0x55, 0x5d, 0x0f, 0xaf, 0x6c, 0x5b, 0xa5, 0x21, // U]..l[.!
0xe5, 0x81, 0xbc, 0x0d, 0x96, 0xee, 0xb4, 0x63, // .......c
0xbc, 0x4c, 0x14, 0x68, 0x6d, 0xfe, 0xd7, 0x64, // .L.hm..d
0x2d, 0xe7, 0x59, 0x9d, 0x8e, 0x20, 0x9c, 0x1c, // -.Y.. ..
0xb1, 0x18, 0x39, 0x38, 0x80, 0xc6, 0x08, 0xa6, // ..98....
0x65, 0x39, 0x6c, 0x0a, 0x86, 0x6c, 0x8b, 0x6a, // e9l..l.j
0xaa, 0x4a, 0x7a, 0xb4, 0xe5, 0x23, 0x7b, 0x9c, // .Jz..#{.
0xa2, 0x88, 0x81, 0xa5, 0x2c, 0x9f, 0x2e, 0xce, // ....,...
0x56, 0xd8, 0x69, 0xc7, 0xd7, 0x54, 0xf8, 0xdd, // V.i..T..
0xab, 0x9b, 0xc7, 0xba, 0x8e, 0xe7, 0x60, 0x1c, // ......`.
0x45, 0x20, 0x09, 0x9d, 0x00, 0x25, 0x16, 0x15, // E ...%..
0xe0, 0x40, 0x2c, 0xf2, 0xac, 0xfa, 0x1f, 0xf8, // .@,.....
0x6d, 0x5e, 0xda, 0xbb, 0x14, 0xaf, 0x4c, 0x82, // m^....L.
0xf3, 0x5d, 0x81, 0xcb, 0xef, 0xcd, 0xa8, 0x0f, // .]......
0xf1, 0xec, 0xa5, 0xa3, 0x44, 0x94, 0x69, 0x7a, // ....D.iz
0x88, 0xec, 0xa9, 0x18, 0xf3, 0xac, 0x38, 0xe6, // ......8.
0xe7, 0xe0, 0xe1, 0x11, 0xa8, 0xa5, 0x5f, 0x18, // ......_.
0x00, 0x72, 0xd0, 0x00, 0x9e, 0x12, 0x89, 0x50, // .r.....P
0x96, 0x20, 0xdb, 0xcd, 0x63, 0xe7, 0xb3, 0xc0, // . ..c...
0xfa, 0x54, 0xa1, 0xe7, 0x4a, 0x74, 0x5d, 0xcd, // .T..Jt].
0x4a, 0x2f, 0x4c, 0x44, 0xa3, 0xdc, 0x40, 0xad, // J/LD..@.
0xe7, 0xdc, 0x4d, 0x9b, 0x2a, 0x55, 0x13, 0x0b, // ..M.*U..
0x4d, 0x4f, 0x3d, 0xc3, 0x02, 0xac, 0xd2, 0x03, // MO=.....
0x70, 0x0a, 0x48, 0xa9, 0x96, 0x5b, 0x04, 0x57, // p.H..[.W
0xb9, 0xe2, 0x5a, 0x04, 0x5e, 0xcf, 0x6f, 0x4e, // ..Z.^.oN
0x4c, 0xf3, 0x8e, 0xa2, 0xd0, 0xd9, 0xcb, 0x01, // L.......
0xbc, 0x8c, 0x14, 0xd5, 0x08, 0xfc, 0x18, 0x08, // ........
0xc1, 0x65, 0x83, 0x3f, 0x0e, 0xa4, 0x17, 0x1c, // .e.?....
0x6e, 0x45, 0x0a, 0xef, 0x1d, 0x40, 0xc4, 0x7b, // nE...@.{
0x6a, 0x7e, 0x5d, 0xa6, 0xde, 0x97, 0x22, 0x7b, // j~]..."{
0x67, 0xbf, 0xc0, 0xa2, 0x83, 0x39, 0xb6, 0xf6, // g....9..
0x15, 0x16, 0xc6, 0x6f, 0x09, 0x61, 0xb1, 0x02, // ...o.a..
0x03, 0x01, 0x00, 0x01, 0xa3, 0x4c, 0x30, 0x4a, // .....L0J
0x30, 0x48, 0x06, 0x03, 0x55, 0x1d, 0x01, 0x04, // 0H..U...
0x41, 0x30, 0x3f, 0x80, 0x10, 0x0d, 0x27, 0x29, // A0?...')
0xe4, 0x05, 0x2a, 0x97, 0xb4, 0x77, 0x58, 0x35, // ..*..wX5
0x47, 0x93, 0x2d, 0x06, 0xb8, 0xa1, 0x1f, 0x30, // G.-....0
0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, // .1.0...U
0x04, 0x03, 0x13, 0x12, 0x52, 0x6f, 0x6f, 0x74, // ....Root
0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x82, 0x0a, // hority..
0x20, 0x9d, 0x11, 0xd1, 0x0e, 0x7f, 0x7b, 0x85, // .....{.
0x74, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, // t.0...*.
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, // H.......
0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2b, 0x02, // ......+.
0x2b, 0x37, 0x66, 0xa5, 0xd1, 0x8c, 0x3e, 0x20, // +7f...>
0x08, 0x1a, 0x0c, 0xb7, 0xf5, 0x63, 0xcb, 0xc6, // .....c..
0xdd, 0x9b, 0x62, 0x52, 0x32, 0xbc, 0x33, 0x74, // ..bR2.3t
0x7a, 0xde, 0xb0, 0x80, 0x05, 0xfa, 0xe5, 0xb5, // z.......
0xe4, 0xf7, 0xf1, 0xd7, 0xa0, 0x95, 0x5c, 0x6c, // .......l
0x05, 0x9b, 0x2f, 0x03, 0x4b, 0xb7, 0x8a, 0x95, // ../.K...
0x0e, 0xb0, 0x06, 0x80, 0xa0, 0x2a, 0x1b, 0xa4, // .....*..
0x09, 0x58, 0xbd, 0x87, 0xd4, 0x38, 0x44, 0xb4, // .X...8D.
0x71, 0x7b, 0xfb, 0x74, 0xa2, 0x89, 0x48, 0xe6, // q{.t..H.
0x5f, 0xab, 0x9a, 0xa4, 0x0a, 0x38, 0xcc, 0x57, // _....8.W
0xa1, 0x14, 0x2c, 0x5c, 0xee, 0xc2, 0x13, 0x81, // ..,.....
0x00, 0xc3, 0x2d, 0xb1, 0x70, 0xde, 0x9f, 0xb1, // ..-.p...
0x70, 0x43, 0x7e, 0x22, 0xa0, 0x77, 0x96, 0xc8, // pC~".w..
0xdf, 0x99, 0xdc, 0xa6, 0x4e, 0xb3, 0xb5, 0x74, // ....N..t
0x34, 0x13, 0x12, 0x24, 0xa2, 0x6b, 0x95, 0x80, // 4..$.k..
0xcf, 0xaa, 0x4a, 0x68, 0xb1, 0x77, 0x27, 0x98, // ..Jh.w'.
0xef, 0xaa, 0x62, 0xd3, 0x22, 0x81, 0x33, 0x2b, // ..b.".3+
0x12, 0x50, 0xef, 0x16, 0x86, 0xe6, 0x9a, 0x5a, // .P.....Z
0x73, 0x89, 0x6d, 0x83, 0xf2, 0x08, 0xa3, 0x13, // s.m.....
0xab, 0x05, 0xd5, 0x6e, 0x68, 0xf6, 0x90, 0xa4, // ...nh...
0x4a, 0x9f, 0x7c, 0x4c, 0x5d, 0x8f, 0x58, 0xf3, // J.|L].X.
0x11, 0x4c, 0xc7, 0x08, 0x51, 0xea, 0x76, 0xd1, // .L..Q.v.
0xb5, 0x55, 0x32, 0x3f, 0xff, 0x67, 0xef, 0x35, // .U2?.g.5
0x8c, 0x89, 0xd3, 0xc6, 0x75, 0x15, 0x68, 0x9f, // ....u.h.
0x67, 0x46, 0x9c, 0x94, 0x41, 0xf5, 0x76, 0x51, // gF..A.vQ
0x86, 0xac, 0x91, 0x75, 0xec, 0xb6, 0xf7, 0x00, // ...u....
0x40, 0x5b, 0xfe, 0x61, 0xd8, 0x33, 0x2d, 0x37, // @[.a.3-7
0x65, 0x8b, 0x94, 0xd9, 0x97, 0x21, 0x15, 0x2c, // e....!.,
0x13, 0x49, 0xff, 0xde, 0xb7, 0x83, 0xd9, 0xae, // .I......
0xc4, 0xce, 0x24, 0xb2, 0x50, 0xdf, 0x75, 0x14, // ..$.P.u.
0x12, 0x8c, 0x46, 0xa4, 0xac, 0xef, 0x4c, 0x72, // ..F...Lr
0x00, 0x00, 0xe1, 0x4c, 0x8e, 0xee }; // ...L..
// Versign Class 3 SGC Root
static CONST BYTE VSCLASS3ROOT[] =
{ 0x30, 0x82, 0x02, 0x31, 0x30, 0x82, 0x01, 0x9a,
0x02, 0x05, 0x02, 0xa1, 0x00, 0x00, 0x01, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x5f,
0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30,
0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e,
0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x37,
0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20,
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30,
0x1e, 0x17, 0x0d, 0x39, 0x36, 0x30, 0x31, 0x32,
0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
0x17, 0x0d, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31,
0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30,
0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17,
0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b,
0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20,
0x33, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79,
0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
0x89, 0x02, 0x81, 0x81, 0x00, 0xc9, 0x5c, 0x59,
0x9e, 0xf2, 0x1b, 0x8a, 0x01, 0x14, 0xb4, 0x10,
0xdf, 0x04, 0x40, 0xdb, 0xe3, 0x57, 0xaf, 0x6a,
0x45, 0x40, 0x8f, 0x84, 0x0c, 0x0b, 0xd1, 0x33,
0xd9, 0xd9, 0x11, 0xcf, 0xee, 0x02, 0x58, 0x1f,
0x25, 0xf7, 0x2a, 0xa8, 0x44, 0x05, 0xaa, 0xec,
0x03, 0x1f, 0x78, 0x7f, 0x9e, 0x93, 0xb9, 0x9a,
0x00, 0xaa, 0x23, 0x7d, 0xd6, 0xac, 0x85, 0xa2,
0x63, 0x45, 0xc7, 0x72, 0x27, 0xcc, 0xf4, 0x4c,
0xc6, 0x75, 0x71, 0xd2, 0x39, 0xef, 0x4f, 0x42,
0xf0, 0x75, 0xdf, 0x0a, 0x90, 0xc6, 0x8e, 0x20,
0x6f, 0x98, 0x0f, 0xf8, 0xac, 0x23, 0x5f, 0x70,
0x29, 0x36, 0xa4, 0xc9, 0x86, 0xe7, 0xb1, 0x9a,
0x20, 0xcb, 0x53, 0xa5, 0x85, 0xe7, 0x3d, 0xbe,
0x7d, 0x9a, 0xfe, 0x24, 0x45, 0x33, 0xdc, 0x76,
0x15, 0xed, 0x0f, 0xa2, 0x71, 0x64, 0x4c, 0x65,
0x2e, 0x81, 0x68, 0x45, 0xa7, 0x02, 0x03, 0x01,
0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05,
0x00, 0x03, 0x81, 0x81, 0x00, 0x75, 0x66, 0x6c,
0x3e, 0xd1, 0xcd, 0x81, 0xdb, 0xb5, 0xf8, 0x2f,
0x36, 0x51, 0xb6, 0xf7, 0x42, 0xbc, 0xcd, 0x42,
0xaf, 0xdc, 0x0e, 0xfa, 0x15, 0x6c, 0xf8, 0x67,
0x93, 0x57, 0x3a, 0xeb, 0xb6, 0x92, 0xe8, 0xb6,
0x01, 0xca, 0x8c, 0xb7, 0x8e, 0x43, 0xb4, 0x49,
0x65, 0xf9, 0x3e, 0xee, 0xbd, 0x75, 0x46, 0x2e,
0xc9, 0xfc, 0x25, 0x5d, 0xa8, 0xc7, 0x2f, 0x8b,
0x9b, 0x8f, 0x68, 0xcf, 0xb4, 0x9c, 0x97, 0x18,
0xc0, 0x4d, 0xef, 0x1f, 0xd9, 0xaf, 0x82, 0xb3,
0xe6, 0x64, 0xb8, 0x84, 0x5c, 0x8a, 0x9a, 0x07,
0x52, 0x43, 0x61, 0xfb, 0x74, 0x9e, 0x5b, 0x3a,
0x36, 0xfc, 0x4c, 0xb2, 0xfc, 0x1a, 0x3f, 0x15,
0x2e, 0xa5, 0x5b, 0x3c, 0x1b, 0x90, 0xec, 0x88,
0x29, 0xe4, 0x59, 0x16, 0xf9, 0xce, 0x07, 0xad,
0xec, 0xe9, 0xdd, 0xda, 0xd2, 0x31, 0x8a, 0x4f,
0xd6, 0xd8, 0xef, 0x17, 0x8d };
// SGC Test Root
#ifdef SGC_TEST_KEY
static CONST BYTE TestSGCRoot[] =
{ 0x30, 0x82, 0x01, 0xda, 0x30, 0x82, 0x01, 0x84, // 0...0...
0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x46, // .......F
0xeb, 0x72, 0x4f, 0xc0, 0x00, 0x78, 0xab, 0x11, // .rO..x..
0xd2, 0x84, 0xb0, 0x35, 0xb8, 0xe0, 0xb1, 0x30, // ...5...0
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, // ...*.H..
0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x26, // ......0&
0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, // 1$0"..U.
0x03, 0x13, 0x1b, 0x53, 0x63, 0x68, 0x61, 0x6e, // ...Schan
0x6e, 0x65, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, // nel Test
0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, // hority0.
0x17, 0x0d, 0x39, 0x38, 0x31, 0x31, 0x32, 0x35, // ..981125
0x32, 0x31, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x17, // 214554Z.
0x0d, 0x33, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, // .3912312
0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x26, // 35959Z0&
0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, // 1$0"..U.
0x03, 0x13, 0x1b, 0x53, 0x63, 0x68, 0x61, 0x6e, // ...Schan
0x6e, 0x65, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, // nel Test
0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x5c, // hority0.
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, // 0...*.H.
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, // ........
0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xd1, // K.0H.A..
0x95, 0x8e, 0x14, 0xc9, 0x8b, 0x28, 0x00, 0xd4, // .....(..
0xed, 0x40, 0xb5, 0xd4, 0xec, 0x1f, 0x67, 0xb1, // .@....g.
0xa2, 0xb3, 0x18, 0xca, 0x6b, 0x48, 0x6c, 0x54, // ....kHlT
0xaf, 0xc4, 0x70, 0x3c, 0x6e, 0xee, 0x15, 0xba, // ..p<n...
0x4b, 0xf7, 0x40, 0x93, 0xd3, 0x35, 0x1d, 0x17, // K.@..5..
0x6c, 0xe8, 0x1d, 0x62, 0xec, 0x74, 0x96, 0x48, // l..b.t.H
0x4f, 0x1e, 0xcf, 0xf0, 0x54, 0x2b, 0x30, 0x0b, // O...T+0.
0x66, 0x3a, 0x83, 0x1c, 0x32, 0xda, 0x3d, 0x02, // f:..2.=.
0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x8d, 0x30, // .......0
0x81, 0x8a, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x1d, // ..0...U.
0x0a, 0x04, 0x06, 0x30, 0x04, 0x03, 0x02, 0x07, // ...0....
0x80, 0x30, 0x20, 0x06, 0x03, 0x55, 0x1d, 0x25, // .0 ..U.%
0x04, 0x19, 0x30, 0x17, 0x06, 0x0a, 0x2b, 0x06, // ..0...+.
0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x03, // ....7...
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, // ..`.H...
0x42, 0x04, 0x01, 0x30, 0x57, 0x06, 0x03, 0x55, // B..0W..U
0x1d, 0x01, 0x04, 0x50, 0x30, 0x4e, 0x80, 0x10, // ...P0N..
0x35, 0x2f, 0x90, 0xa8, 0x13, 0xd6, 0x82, 0x32, // 5......2
0x85, 0x1a, 0x5d, 0x0f, 0xdc, 0x83, 0xe3, 0x28, // ..]....(
0xa1, 0x28, 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, // .(0&1$0"
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x53, // ..U....S
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, // channel
0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x47, 0x43, // Test SGC
0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, // Authori
0x74, 0x79, 0x82, 0x10, 0x46, 0xeb, 0x72, 0x4f, // ty..F.rO
0xc0, 0x00, 0x78, 0xab, 0x11, 0xd2, 0x84, 0xb0, // ..x.....
0x35, 0xb8, 0xe0, 0xb1, 0x30, 0x0d, 0x06, 0x09, // 5...0...
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, // *.H.....
0x04, 0x05, 0x00, 0x03, 0x41, 0x00, 0x65, 0x35, // ....A.e5
0x80, 0xaf, 0xa3, 0xba, 0x5d, 0x13, 0xcd, 0x86, // ....]...
0xad, 0xda, 0x06, 0xb6, 0xb3, 0x51, 0xf4, 0x71, // .....Q.q
0x4a, 0x0b, 0xd2, 0xc1, 0x91, 0x13, 0xc3, 0x0c, // J.......
0xd7, 0xb7, 0x9f, 0xa6, 0x3c, 0x04, 0xfa, 0xb7, // ....<...
0x97, 0x94, 0x64, 0xf0, 0x5b, 0xab, 0x65, 0x3b, // ..d.[.e;
0x88, 0x95, 0x59, 0x4c, 0x18, 0x11, 0xc4, 0xac, // ..YL....
0x5c, 0x6e, 0x31, 0xf0, 0xdd, 0x74, 0xc1, 0x55, // .n1..t.U
0x7e, 0x7f, 0x66, 0xf4, 0x8a, 0x57 }; // ~.f..W
#endif // SGC_TEST_KEY
typedef struct SGC_ROOT
{
CONST BYTE * pbCert;
DWORD cbCert;
PCCERT_CONTEXT pCertContext;
} SGC_ROOT, *PSGC_ROOT;
static SGC_ROOT SGCRoots[] = {
{ GenevaSGCRoot, sizeof(GenevaSGCRoot), NULL },
{ VSCLASS3ROOT, sizeof(VSCLASS3ROOT), NULL },
#ifdef SGC_TEST_KEY
{ TestSGCRoot, sizeof(TestSGCRoot), NULL }
#endif // SGC_TEST_KEY
};
static CONST DWORD SGCRootCount = sizeof(SGCRoots) / sizeof(SGC_ROOT);
static CONST LPCSTR rgSGCExtensions[]
= { szOID_SGC_NETSCAPE,
szOID_SERVER_GATED_CRYPTO };
static CONST CERT_ENHKEY_USAGE SGCExtensions
= { sizeof(rgSGCExtensions)/sizeof(LPSTR),
(LPSTR *)rgSGCExtensions };
//
// Load root certs
//
DWORD
LoadSGCRoots(
IN CRITICAL_SECTION *pCritSec) // must be initialized
{
DWORD dwReturn = ERROR_INTERNAL_ERROR;
BOOL fInCritSec = FALSE;
BOOL fLoadRoots = FALSE;
DWORD i;
// check if the Roots are already loaded
for (i = 0; i < SGCRootCount; i++)
{
if (SGCRoots[i].pCertContext == NULL)
{
fLoadRoots = TRUE;
break;
}
}
if (!fLoadRoots)
{
dwReturn = ERROR_SUCCESS;
goto ErrorExit;
}
// wrap with a try since there is a critical sections in here
__try
{
// take the critical section
EnterCriticalSection(pCritSec);
fInCritSec = TRUE;
for (i = 0; i < SGCRootCount; i++)
{
if (SGCRoots[i].pCertContext == NULL)
{
SGCRoots[i].pCertContext = CertCreateCertificateContext(
X509_ASN_ENCODING,
SGCRoots[i].pbCert,
SGCRoots[i].cbCert);
if (NULL == SGCRoots[i].pCertContext)
{
dwReturn = GetLastError();
goto ErrorExit;
}
}
}
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
// ?BUGBUG? Could be resource exhaustion
dwReturn = ERROR_INVALID_PARAMETER;
goto ErrorExit;
}
dwReturn = ERROR_SUCCESS;
ErrorExit:
if (fInCritSec)
LeaveCriticalSection(pCritSec);
return dwReturn;
}
//
// delete the public key values
//
void
SGCDeletePubKeyValues(
IN OUT BYTE **ppbKeyMod,
IN OUT DWORD *pcbKeyMod,
IN OUT DWORD *pdwKeyExpo)
{
if (*ppbKeyMod)
SGCFree(*ppbKeyMod);
*ppbKeyMod = NULL;
*pcbKeyMod = 0;
*pdwKeyExpo = 0;
}
//
// get the public key form the cert context and assign it to the
// passed in parameters
//
DWORD
SGCAssignPubKey(
IN PCCERT_CONTEXT pCertContext,
IN OUT BYTE **ppbKeyMod,
IN OUT DWORD *pcbKeyMod,
IN OUT DWORD *pdwKeyExpo)
{
DWORD dwReturn = ERROR_INTERNAL_ERROR;
BLOBHEADER *pBlob = NULL;
DWORD cbBlob = 0;
RSAPUBKEY *pRSAPubKey;
BYTE *pb;
// decode the public key from the cert into a PUBLICKEYBLOB
if (!CryptDecodeObject(X509_ASN_ENCODING,
RSA_CSP_PUBLICKEYBLOB,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
0,
NULL,
&cbBlob))
{
dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
goto ErrorExit;
}
pBlob = (BLOBHEADER*)SGCAlloc(cbBlob);
if (NULL == pBlob)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
goto ErrorExit;
}
if (!CryptDecodeObject(X509_ASN_ENCODING,
RSA_CSP_PUBLICKEYBLOB,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
0,
pBlob,
&cbBlob))
{
dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
goto ErrorExit;
}
pRSAPubKey = (RSAPUBKEY*)((BYTE*)pBlob + sizeof(BLOBHEADER));
// delete any old public key info
SGCDeletePubKeyValues(ppbKeyMod, pcbKeyMod, pdwKeyExpo);
// assign public key values
*pdwKeyExpo = pRSAPubKey->pubexp;
*pcbKeyMod = pRSAPubKey->bitlen / 8;
*ppbKeyMod = (BYTE*)SGCAlloc(*pcbKeyMod);
if (NULL == *ppbKeyMod)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
goto ErrorExit;
}
pb = (BYTE*)pRSAPubKey + sizeof(RSAPUBKEY);
memcpy(*ppbKeyMod, pb, *pcbKeyMod);
dwReturn = ERROR_SUCCESS;
ErrorExit:
if (pBlob)
SGCFree(pBlob);
return dwReturn;
}
//
// check if the passed in public key matches the one in the cert
//
static DWORD
SamePublicKey(
IN PCCERT_CONTEXT pCertContext,
IN BYTE *pbExchKeyMod,
IN DWORD cbExchKeyMod,
IN DWORD dwExchKeyExpo)
{
DWORD dwReturn = ERROR_INTERNAL_ERROR;
BLOBHEADER *pBlob = NULL;
DWORD cbBlob = 0;
RSAPUBKEY *pRSAPubKey;
BYTE *pb;
// decode the public key from the cert into a PUBLICKEYBLOB
if (!CryptDecodeObject(X509_ASN_ENCODING,
RSA_CSP_PUBLICKEYBLOB,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
0,
NULL,
&cbBlob))
{
dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
goto ErrorExit;
}
pBlob = (BLOBHEADER*)SGCAlloc(cbBlob);
if (NULL == pBlob)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
goto ErrorExit;
}
if (!CryptDecodeObject(X509_ASN_ENCODING,
RSA_CSP_PUBLICKEYBLOB,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
0,
pBlob,
&cbBlob))
{
dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
goto ErrorExit;
}
pRSAPubKey = (RSAPUBKEY*)((BYTE*)pBlob + sizeof(BLOBHEADER));
// check the length of the modulus and the exponent
if (((pRSAPubKey->bitlen / 8) != cbExchKeyMod) ||
(pRSAPubKey->pubexp != dwExchKeyExpo))
{
dwReturn = (DWORD)NTE_BAD_DATA;
goto ErrorExit;
}
// check that the modulus values match
pb = (BYTE*)pRSAPubKey + sizeof(RSAPUBKEY);
if (0 != memcmp(pbExchKeyMod, pb, cbExchKeyMod))
{
dwReturn = (DWORD)NTE_BAD_DATA;
goto ErrorExit;
}
dwReturn = ERROR_SUCCESS;
ErrorExit:
if (pBlob)
SGCFree(pBlob);
return dwReturn;
}
static DWORD
ReadSgcExtensions(
PCCERT_CONTEXT pCertContext)
{
PCERT_EXTENSION pExt;
PCTL_USAGE pUsage = NULL;
DWORD cbUsage;
DWORD dwSGCFlags = 0;
DWORD i;
pExt = CertFindExtension(szOID_ENHANCED_KEY_USAGE,
pCertContext->pCertInfo->cExtension,
pCertContext->pCertInfo->rgExtension);
if (pExt == NULL)
goto cleanup;
if (!CryptDecodeObject(X509_ASN_ENCODING,
X509_ENHANCED_KEY_USAGE,
pExt->Value.pbData,
pExt->Value.cbData,
0,
NULL,
&cbUsage))
{
goto cleanup;
}
pUsage = (PCTL_USAGE)SGCAlloc(cbUsage);
if (pUsage == NULL)
goto cleanup;
if (!CryptDecodeObject(X509_ASN_ENCODING,
X509_ENHANCED_KEY_USAGE,
pExt->Value.pbData,
pExt->Value.cbData,
0,
pUsage,
&cbUsage))
{
goto cleanup;
}
for (i = 0; i < pUsage->cUsageIdentifier; i++)
{
if (0 == strcmp(pUsage->rgpszUsageIdentifier[i],
szOID_SGC_NETSCAPE))
{
dwSGCFlags |= CRYPT_SGC;
}
else if (0 == strcmp(pUsage->rgpszUsageIdentifier[i],
szOID_SERVER_GATED_CRYPTO))
{
dwSGCFlags |= CRYPT_FASTSGC | CRYPT_SGC;
}
}
cleanup:
if (pUsage)
SGCFree(pUsage);
return dwSGCFlags;
}
//+---------------------------------------------------------------------------
//
// Function: FindBridgeCertificate
//
// Synopsis: Search the specified certificate store for a valid SGC
// bridge certificate.
//
// Arguments: [hCAStore] -- Certificate store to search. This is
// typically the CA store.
//
// [pChainContext] -- Certificate chain for which we are finding
// a bridge certificate. The bridge cert
// may branch off of any certificate in the
// chain.
//
// [pRootContext] -- Handle to baked-in SGC root certificate
// (typically Geneva).
//
// History: 11-16-98 jbanes Created
//
// Notes: An SGC bridge certificate is defined as a certificate with a
// SUBJECT equal to the ISSUER in one of the 'pChainContext'
// certificates. To be valid, the bridge certificate must
// contain at least one SGC EKU and it must chain up to a
// baked-in SGC root certificate.
//
// Returns: TRUE if a valid SGC bridge cert was found, and FALSE
// otherwise.
//
//----------------------------------------------------------------------------
static BOOL
FindBridgeCertificate(
IN HCERTSTORE hCAStore,
IN PCCERT_CHAIN_CONTEXT pChainContext,
IN PCCERT_CONTEXT pRootContext)
{
PCERT_SIMPLE_CHAIN pSimpleChain;
PCCERT_CONTEXT pCurrent = NULL;
PCCERT_CONTEXT pCurrentCA = NULL;
PCCERT_CHAIN_CONTEXT pCAChainContext = NULL;
CERT_CHAIN_PARA ChainPara;
CERT_TRUST_STATUS TrustStatus;
BOOL fFound;
DWORD i;
BOOL fRet = FALSE;
DWORD dwFlags;
//
// Enumerate all of the certificates in the CA store that contain
// one of the SGC extensions.
//
pCurrent = NULL;
for (;;)
{
// Find an SGC intermediate certificate.
pCurrentCA = CertFindCertificateInStore(
hCAStore,
X509_ASN_ENCODING,
CERT_FIND_OR_ENHKEY_USAGE_FLAG,
CERT_COMPARE_ENHKEY_USAGE,
&SGCExtensions,
pCurrentCA);
if (pCurrentCA == NULL)
break;
//
// Is this CA certificate a bridge for any of the certificates in the
// passed in certificate chain?
//
fFound = FALSE;
pSimpleChain = pChainContext->rgpChain[0];
for (i = 0; i < pSimpleChain->cElement; i++)
{
pCurrent = pSimpleChain->rgpElement[i]->pCertContext;
if (ReadSgcExtensions(pCurrent) == 0)
{
// This certificate doesn't contain any SGC certificate
// extensions, so skip the rest of this chain.
break;
}
if (CertCompareCertificateName(X509_ASN_ENCODING,
&pCurrentCA->pCertInfo->Subject,
&pCurrent->pCertInfo->Issuer))
{
// The names match. Now check the signature.
dwFlags = SGC_VERIFICATION_FLAGS;
if (!CertVerifySubjectCertificateContext(pCurrent,
pCurrentCA,
&dwFlags))
{
// Error checking signature.
continue;
}
if (dwFlags & SGC_VERIFICATION_FLAGS)
{
// Signature did not verify or certificate expired.
continue;
}
fFound = TRUE;
break;
}
}
if (!fFound)
continue;
//
// Does this CA certificate chain up to Geneva?
//
ZeroMemory(&ChainPara, sizeof(ChainPara));
ChainPara.cbSize = sizeof(ChainPara);
if (!CertGetCertificateChain(NULL,
pCurrentCA,
NULL,
hCAStore,
&ChainPara,
0,
NULL,
&pCAChainContext))
{
// Error building chain.
continue;
}
pSimpleChain = pCAChainContext->rgpChain[0];
for (i = 0; i < pSimpleChain->cElement; i++)
{
pCurrent = pSimpleChain->rgpElement[i]->pCertContext;
// Determine if certificate is signed correctly.
TrustStatus = pSimpleChain->rgpElement[i]->TrustStatus;
if (0 != (TrustStatus.dwErrorStatus
& CERT_TRUST_IS_NOT_SIGNATURE_VALID))
{
break;
}
// Is issuer Geneva?
if (CertCompareCertificateName(pCurrent->dwCertEncodingType,
&pCurrent->pCertInfo->Issuer,
&pRootContext->pCertInfo->Subject))
{
// Verify the signature of the current certificate using the
// validated root certificate from the schannel resource.
dwFlags = SGC_VERIFICATION_FLAGS;
if (!CertVerifySubjectCertificateContext(pCurrent,
pRootContext,
&dwFlags))
{
break;
}
if (dwFlags & SGC_VERIFICATION_FLAGS)
break;
fRet = TRUE;
goto ErrorExit;
}
}
}
ErrorExit:
if (pCurrentCA)
CertFreeCertificateContext(pCurrentCA);
if (pCAChainContext)
CertFreeCertificateChain(pCAChainContext);
return fRet;
}
//
// check if the context may be SGC enabled
//
DWORD
SPQueryCFLevel(
IN PCCERT_CONTEXT pCertContext,
IN BYTE *pbExchKeyMod,
IN DWORD cbExchKeyMod,
IN DWORD dwExchKeyExpo,
OUT DWORD *pdwSGCFlags)
{
DWORD dwReturn = ERROR_INTERNAL_ERROR;
DWORD i, j;
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
CERT_CHAIN_PARA ChainPara;
PCERT_SIMPLE_CHAIN pSimpleChain;
CERT_TRUST_STATUS TrustStatus;
HCERTSTORE hCAStore = NULL;
PCCERT_CONTEXT pCurrent = NULL;
PCCERT_CONTEXT pIssuer = NULL;
DWORD dwFlags;
DWORD dwSgcFlags;
DWORD dwSts;
*pdwSGCFlags = 0;
//
// check if the passed in public key matches the one in the cert
//
if (pbExchKeyMod)
{
dwSts = SamePublicKey(pCertContext, pbExchKeyMod,
cbExchKeyMod, dwExchKeyExpo);
if (ERROR_SUCCESS != dwSts)
{
dwReturn = dwSts;
goto ErrorExit;
}
}
//
// Does the leaf certificate contain any SGC extensions?
//
dwSgcFlags = ReadSgcExtensions(pCertContext);
if (dwSgcFlags == 0)
{
// No SGC extensions found.
dwReturn = ERROR_SUCCESS;
goto ErrorExit;
}
//
// Build a certificate chain.
//
ZeroMemory(&ChainPara, sizeof(ChainPara));
ChainPara.cbSize = sizeof(ChainPara);
*pdwSGCFlags = 0;
if (!CertGetCertificateChain(
NULL,
pCertContext,
NULL,
pCertContext->hCertStore,
&ChainPara,
0,
NULL,
&pChainContext))
{
dwReturn = GetLastError();
goto ErrorExit;
}
//
// Does the leaf chain directly up to the Geneva root?
//
pSimpleChain = pChainContext->rgpChain[0];
for (i = 0; i < pSimpleChain->cElement; i++)
{
pCurrent = pSimpleChain->rgpElement[i]->pCertContext;
if (ReadSgcExtensions(pCurrent) == 0)
{
// This certificate doesn't contain any SGC certificate
// extensions, so skip the rest of this chain.
break;
}
TrustStatus = pSimpleChain->rgpElement[i]->TrustStatus;
if (0 != (TrustStatus.dwErrorStatus
& CERT_TRUST_IS_NOT_SIGNATURE_VALID))
{
// Certificate is not signed correctly.
dwReturn = (DWORD)NTE_BAD_SIGNATURE;
goto ErrorExit;
}
// Is Geneva issuer of "pCurrent"?
for (j = 0; j < SGCRootCount; j++)
{
dwFlags = SGC_VERIFICATION_FLAGS;
if (!CertVerifySubjectCertificateContext(
pCurrent,
SGCRoots[j].pCertContext,
&dwFlags))
{
continue;
}
if (dwFlags & SGC_VERIFICATION_FLAGS)
{
continue;
}
// We made it, so set the SGC flags as appropriate.
*pdwSGCFlags |= dwSgcFlags;
dwReturn = ERROR_SUCCESS;
goto ErrorExit;
}
}
//
// Search for bridge certificate.
//
hCAStore = CertOpenSystemStore(0, "CA");
if (NULL == hCAStore)
{
dwReturn = GetLastError();
goto ErrorExit;
}
for (i = 0; i < SGCRootCount; i++)
{
if (SGCRoots[i].pCertContext != NULL)
{
if (FindBridgeCertificate(hCAStore,
pChainContext,
SGCRoots[i].pCertContext))
{
// We made it, so set the SGC flags as appropriate.
*pdwSGCFlags |= dwSgcFlags;
dwReturn = ERROR_SUCCESS;
goto ErrorExit;
}
}
}
dwReturn = (DWORD)NTE_FAIL;
ErrorExit:
if (pIssuer)
CertFreeCertificateContext(pIssuer);
if (pChainContext)
CertFreeCertificateChain(pChainContext);
if (hCAStore)
CertCloseStore(hCAStore, 0);
return dwReturn;
}