956 lines
34 KiB
C
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;
|
||
|
}
|
||
|
|