|
|
/////////////////////////////////////////////////////////////////////////////
// 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, // [email protected].
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, // [email protected]..
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; }
|