Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

955 lines
34 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : sgccheck.c //
  3. // DESCRIPTION : Code to check if SGC is enabled //
  4. // AUTHOR : jeffspel //
  5. // HISTORY : //
  6. // Jun 16 1998 jeffspel Create //
  7. // Nov 16 1998 jbanes Pluggable SGC roots. //
  8. // //
  9. // Copyright (C) 1998 Microsoft Corporation All Rights Reserved //
  10. /////////////////////////////////////////////////////////////////////////////
  11. #include <windows.h>
  12. #include <windef.h>
  13. #include <wincrypt.h>
  14. #include <sgccheck.h>
  15. #define SGCAlloc(cb) LocalAlloc(LMEM_ZEROINIT, cb)
  16. #define SGCFree(pb) LocalFree(pb)
  17. //#define SGC_TEST_KEY // COMMENT OUT THIS LINE BEFORE CHECKING IN!!!
  18. #ifdef SGC_TEST_KEY
  19. #pragma message ("WARNING -- Building with SGC Test Key enabled.")
  20. #endif
  21. #define SGC_VERIFICATION_FLAGS (CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG)
  22. // Geneva SGC Root
  23. static CONST BYTE GenevaSGCRoot[] =
  24. { 0x30, 0x82, 0x03, 0x0a, 0x30, 0x82, 0x01, 0xf2, // 0...0...
  25. 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x20, // .......
  26. 0x9d, 0x11, 0xd1, 0x0e, 0x7f, 0x7b, 0x85, 0x74, // .....{.t
  27. 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, // .0...*.H
  28. 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, // ........
  29. 0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, // 0.1.0...
  30. 0x55, 0x04, 0x03, 0x13, 0x12, 0x52, 0x6f, 0x6f, // U....Roo
  31. 0x74, 0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, // t SGC Au
  32. 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, // thority0
  33. 0x1e, 0x17, 0x0d, 0x39, 0x37, 0x30, 0x38, 0x30, // ...97080
  34. 0x36, 0x31, 0x37, 0x31, 0x34, 0x34, 0x37, 0x5a, // 6171447Z
  35. 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, // ..100101
  36. 0x30, 0x37, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, // 070000Z0
  37. 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, // .1.0...U
  38. 0x04, 0x03, 0x13, 0x12, 0x52, 0x6f, 0x6f, 0x74, // ....Root
  39. 0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
  40. 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, // hority0.
  41. 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, // ."0...*.
  42. 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, // H.......
  43. 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, // ......0.
  44. 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xec, // ........
  45. 0x55, 0x5d, 0x0f, 0xaf, 0x6c, 0x5b, 0xa5, 0x21, // U]..l[.!
  46. 0xe5, 0x81, 0xbc, 0x0d, 0x96, 0xee, 0xb4, 0x63, // .......c
  47. 0xbc, 0x4c, 0x14, 0x68, 0x6d, 0xfe, 0xd7, 0x64, // .L.hm..d
  48. 0x2d, 0xe7, 0x59, 0x9d, 0x8e, 0x20, 0x9c, 0x1c, // -.Y.. ..
  49. 0xb1, 0x18, 0x39, 0x38, 0x80, 0xc6, 0x08, 0xa6, // ..98....
  50. 0x65, 0x39, 0x6c, 0x0a, 0x86, 0x6c, 0x8b, 0x6a, // e9l..l.j
  51. 0xaa, 0x4a, 0x7a, 0xb4, 0xe5, 0x23, 0x7b, 0x9c, // .Jz..#{.
  52. 0xa2, 0x88, 0x81, 0xa5, 0x2c, 0x9f, 0x2e, 0xce, // ....,...
  53. 0x56, 0xd8, 0x69, 0xc7, 0xd7, 0x54, 0xf8, 0xdd, // V.i..T..
  54. 0xab, 0x9b, 0xc7, 0xba, 0x8e, 0xe7, 0x60, 0x1c, // ......`.
  55. 0x45, 0x20, 0x09, 0x9d, 0x00, 0x25, 0x16, 0x15, // E ...%..
  56. 0xe0, 0x40, 0x2c, 0xf2, 0xac, 0xfa, 0x1f, 0xf8, // .@,.....
  57. 0x6d, 0x5e, 0xda, 0xbb, 0x14, 0xaf, 0x4c, 0x82, // m^....L.
  58. 0xf3, 0x5d, 0x81, 0xcb, 0xef, 0xcd, 0xa8, 0x0f, // .]......
  59. 0xf1, 0xec, 0xa5, 0xa3, 0x44, 0x94, 0x69, 0x7a, // ....D.iz
  60. 0x88, 0xec, 0xa9, 0x18, 0xf3, 0xac, 0x38, 0xe6, // ......8.
  61. 0xe7, 0xe0, 0xe1, 0x11, 0xa8, 0xa5, 0x5f, 0x18, // ......_.
  62. 0x00, 0x72, 0xd0, 0x00, 0x9e, 0x12, 0x89, 0x50, // .r.....P
  63. 0x96, 0x20, 0xdb, 0xcd, 0x63, 0xe7, 0xb3, 0xc0, // . ..c...
  64. 0xfa, 0x54, 0xa1, 0xe7, 0x4a, 0x74, 0x5d, 0xcd, // .T..Jt].
  65. 0x4a, 0x2f, 0x4c, 0x44, 0xa3, 0xdc, 0x40, 0xad, // J/LD..@.
  66. 0xe7, 0xdc, 0x4d, 0x9b, 0x2a, 0x55, 0x13, 0x0b, // ..M.*U..
  67. 0x4d, 0x4f, 0x3d, 0xc3, 0x02, 0xac, 0xd2, 0x03, // MO=.....
  68. 0x70, 0x0a, 0x48, 0xa9, 0x96, 0x5b, 0x04, 0x57, // p.H..[.W
  69. 0xb9, 0xe2, 0x5a, 0x04, 0x5e, 0xcf, 0x6f, 0x4e, // ..Z.^.oN
  70. 0x4c, 0xf3, 0x8e, 0xa2, 0xd0, 0xd9, 0xcb, 0x01, // L.......
  71. 0xbc, 0x8c, 0x14, 0xd5, 0x08, 0xfc, 0x18, 0x08, // ........
  72. 0xc1, 0x65, 0x83, 0x3f, 0x0e, 0xa4, 0x17, 0x1c, // .e.?....
  73. 0x6e, 0x45, 0x0a, 0xef, 0x1d, 0x40, 0xc4, 0x7b, // nE...@.{
  74. 0x6a, 0x7e, 0x5d, 0xa6, 0xde, 0x97, 0x22, 0x7b, // j~]..."{
  75. 0x67, 0xbf, 0xc0, 0xa2, 0x83, 0x39, 0xb6, 0xf6, // g....9..
  76. 0x15, 0x16, 0xc6, 0x6f, 0x09, 0x61, 0xb1, 0x02, // ...o.a..
  77. 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4c, 0x30, 0x4a, // .....L0J
  78. 0x30, 0x48, 0x06, 0x03, 0x55, 0x1d, 0x01, 0x04, // 0H..U...
  79. 0x41, 0x30, 0x3f, 0x80, 0x10, 0x0d, 0x27, 0x29, // A0?...')
  80. 0xe4, 0x05, 0x2a, 0x97, 0xb4, 0x77, 0x58, 0x35, // ..*..wX5
  81. 0x47, 0x93, 0x2d, 0x06, 0xb8, 0xa1, 0x1f, 0x30, // G.-....0
  82. 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, // .1.0...U
  83. 0x04, 0x03, 0x13, 0x12, 0x52, 0x6f, 0x6f, 0x74, // ....Root
  84. 0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
  85. 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x82, 0x0a, // hority..
  86. 0x20, 0x9d, 0x11, 0xd1, 0x0e, 0x7f, 0x7b, 0x85, // .....{.
  87. 0x74, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, // t.0...*.
  88. 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, // H.......
  89. 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2b, 0x02, // ......+.
  90. 0x2b, 0x37, 0x66, 0xa5, 0xd1, 0x8c, 0x3e, 0x20, // +7f...>
  91. 0x08, 0x1a, 0x0c, 0xb7, 0xf5, 0x63, 0xcb, 0xc6, // .....c..
  92. 0xdd, 0x9b, 0x62, 0x52, 0x32, 0xbc, 0x33, 0x74, // ..bR2.3t
  93. 0x7a, 0xde, 0xb0, 0x80, 0x05, 0xfa, 0xe5, 0xb5, // z.......
  94. 0xe4, 0xf7, 0xf1, 0xd7, 0xa0, 0x95, 0x5c, 0x6c, // .......l
  95. 0x05, 0x9b, 0x2f, 0x03, 0x4b, 0xb7, 0x8a, 0x95, // ../.K...
  96. 0x0e, 0xb0, 0x06, 0x80, 0xa0, 0x2a, 0x1b, 0xa4, // .....*..
  97. 0x09, 0x58, 0xbd, 0x87, 0xd4, 0x38, 0x44, 0xb4, // .X...8D.
  98. 0x71, 0x7b, 0xfb, 0x74, 0xa2, 0x89, 0x48, 0xe6, // q{.t..H.
  99. 0x5f, 0xab, 0x9a, 0xa4, 0x0a, 0x38, 0xcc, 0x57, // _....8.W
  100. 0xa1, 0x14, 0x2c, 0x5c, 0xee, 0xc2, 0x13, 0x81, // ..,.....
  101. 0x00, 0xc3, 0x2d, 0xb1, 0x70, 0xde, 0x9f, 0xb1, // ..-.p...
  102. 0x70, 0x43, 0x7e, 0x22, 0xa0, 0x77, 0x96, 0xc8, // pC~".w..
  103. 0xdf, 0x99, 0xdc, 0xa6, 0x4e, 0xb3, 0xb5, 0x74, // ....N..t
  104. 0x34, 0x13, 0x12, 0x24, 0xa2, 0x6b, 0x95, 0x80, // 4..$.k..
  105. 0xcf, 0xaa, 0x4a, 0x68, 0xb1, 0x77, 0x27, 0x98, // ..Jh.w'.
  106. 0xef, 0xaa, 0x62, 0xd3, 0x22, 0x81, 0x33, 0x2b, // ..b.".3+
  107. 0x12, 0x50, 0xef, 0x16, 0x86, 0xe6, 0x9a, 0x5a, // .P.....Z
  108. 0x73, 0x89, 0x6d, 0x83, 0xf2, 0x08, 0xa3, 0x13, // s.m.....
  109. 0xab, 0x05, 0xd5, 0x6e, 0x68, 0xf6, 0x90, 0xa4, // ...nh...
  110. 0x4a, 0x9f, 0x7c, 0x4c, 0x5d, 0x8f, 0x58, 0xf3, // J.|L].X.
  111. 0x11, 0x4c, 0xc7, 0x08, 0x51, 0xea, 0x76, 0xd1, // .L..Q.v.
  112. 0xb5, 0x55, 0x32, 0x3f, 0xff, 0x67, 0xef, 0x35, // .U2?.g.5
  113. 0x8c, 0x89, 0xd3, 0xc6, 0x75, 0x15, 0x68, 0x9f, // ....u.h.
  114. 0x67, 0x46, 0x9c, 0x94, 0x41, 0xf5, 0x76, 0x51, // gF..A.vQ
  115. 0x86, 0xac, 0x91, 0x75, 0xec, 0xb6, 0xf7, 0x00, // ...u....
  116. 0x40, 0x5b, 0xfe, 0x61, 0xd8, 0x33, 0x2d, 0x37, // @[.a.3-7
  117. 0x65, 0x8b, 0x94, 0xd9, 0x97, 0x21, 0x15, 0x2c, // e....!.,
  118. 0x13, 0x49, 0xff, 0xde, 0xb7, 0x83, 0xd9, 0xae, // .I......
  119. 0xc4, 0xce, 0x24, 0xb2, 0x50, 0xdf, 0x75, 0x14, // ..$.P.u.
  120. 0x12, 0x8c, 0x46, 0xa4, 0xac, 0xef, 0x4c, 0x72, // ..F...Lr
  121. 0x00, 0x00, 0xe1, 0x4c, 0x8e, 0xee }; // ...L..
  122. // Versign Class 3 SGC Root
  123. static CONST BYTE VSCLASS3ROOT[] =
  124. { 0x30, 0x82, 0x02, 0x31, 0x30, 0x82, 0x01, 0x9a,
  125. 0x02, 0x05, 0x02, 0xa1, 0x00, 0x00, 0x01, 0x30,
  126. 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
  127. 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x5f,
  128. 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
  129. 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30,
  130. 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e,
  131. 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
  132. 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x37,
  133. 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
  134. 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33,
  135. 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
  136. 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20,
  137. 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
  138. 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75,
  139. 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30,
  140. 0x1e, 0x17, 0x0d, 0x39, 0x36, 0x30, 0x31, 0x32,
  141. 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
  142. 0x17, 0x0d, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31,
  143. 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30,
  144. 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
  145. 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17,
  146. 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
  147. 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
  148. 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
  149. 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b,
  150. 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20,
  151. 0x33, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
  152. 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
  153. 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
  154. 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41,
  155. 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79,
  156. 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
  157. 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
  158. 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
  159. 0x89, 0x02, 0x81, 0x81, 0x00, 0xc9, 0x5c, 0x59,
  160. 0x9e, 0xf2, 0x1b, 0x8a, 0x01, 0x14, 0xb4, 0x10,
  161. 0xdf, 0x04, 0x40, 0xdb, 0xe3, 0x57, 0xaf, 0x6a,
  162. 0x45, 0x40, 0x8f, 0x84, 0x0c, 0x0b, 0xd1, 0x33,
  163. 0xd9, 0xd9, 0x11, 0xcf, 0xee, 0x02, 0x58, 0x1f,
  164. 0x25, 0xf7, 0x2a, 0xa8, 0x44, 0x05, 0xaa, 0xec,
  165. 0x03, 0x1f, 0x78, 0x7f, 0x9e, 0x93, 0xb9, 0x9a,
  166. 0x00, 0xaa, 0x23, 0x7d, 0xd6, 0xac, 0x85, 0xa2,
  167. 0x63, 0x45, 0xc7, 0x72, 0x27, 0xcc, 0xf4, 0x4c,
  168. 0xc6, 0x75, 0x71, 0xd2, 0x39, 0xef, 0x4f, 0x42,
  169. 0xf0, 0x75, 0xdf, 0x0a, 0x90, 0xc6, 0x8e, 0x20,
  170. 0x6f, 0x98, 0x0f, 0xf8, 0xac, 0x23, 0x5f, 0x70,
  171. 0x29, 0x36, 0xa4, 0xc9, 0x86, 0xe7, 0xb1, 0x9a,
  172. 0x20, 0xcb, 0x53, 0xa5, 0x85, 0xe7, 0x3d, 0xbe,
  173. 0x7d, 0x9a, 0xfe, 0x24, 0x45, 0x33, 0xdc, 0x76,
  174. 0x15, 0xed, 0x0f, 0xa2, 0x71, 0x64, 0x4c, 0x65,
  175. 0x2e, 0x81, 0x68, 0x45, 0xa7, 0x02, 0x03, 0x01,
  176. 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
  177. 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05,
  178. 0x00, 0x03, 0x81, 0x81, 0x00, 0x75, 0x66, 0x6c,
  179. 0x3e, 0xd1, 0xcd, 0x81, 0xdb, 0xb5, 0xf8, 0x2f,
  180. 0x36, 0x51, 0xb6, 0xf7, 0x42, 0xbc, 0xcd, 0x42,
  181. 0xaf, 0xdc, 0x0e, 0xfa, 0x15, 0x6c, 0xf8, 0x67,
  182. 0x93, 0x57, 0x3a, 0xeb, 0xb6, 0x92, 0xe8, 0xb6,
  183. 0x01, 0xca, 0x8c, 0xb7, 0x8e, 0x43, 0xb4, 0x49,
  184. 0x65, 0xf9, 0x3e, 0xee, 0xbd, 0x75, 0x46, 0x2e,
  185. 0xc9, 0xfc, 0x25, 0x5d, 0xa8, 0xc7, 0x2f, 0x8b,
  186. 0x9b, 0x8f, 0x68, 0xcf, 0xb4, 0x9c, 0x97, 0x18,
  187. 0xc0, 0x4d, 0xef, 0x1f, 0xd9, 0xaf, 0x82, 0xb3,
  188. 0xe6, 0x64, 0xb8, 0x84, 0x5c, 0x8a, 0x9a, 0x07,
  189. 0x52, 0x43, 0x61, 0xfb, 0x74, 0x9e, 0x5b, 0x3a,
  190. 0x36, 0xfc, 0x4c, 0xb2, 0xfc, 0x1a, 0x3f, 0x15,
  191. 0x2e, 0xa5, 0x5b, 0x3c, 0x1b, 0x90, 0xec, 0x88,
  192. 0x29, 0xe4, 0x59, 0x16, 0xf9, 0xce, 0x07, 0xad,
  193. 0xec, 0xe9, 0xdd, 0xda, 0xd2, 0x31, 0x8a, 0x4f,
  194. 0xd6, 0xd8, 0xef, 0x17, 0x8d };
  195. // SGC Test Root
  196. #ifdef SGC_TEST_KEY
  197. static CONST BYTE TestSGCRoot[] =
  198. { 0x30, 0x82, 0x01, 0xda, 0x30, 0x82, 0x01, 0x84, // 0...0...
  199. 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x46, // .......F
  200. 0xeb, 0x72, 0x4f, 0xc0, 0x00, 0x78, 0xab, 0x11, // .rO..x..
  201. 0xd2, 0x84, 0xb0, 0x35, 0xb8, 0xe0, 0xb1, 0x30, // ...5...0
  202. 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, // ...*.H..
  203. 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x26, // ......0&
  204. 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, // 1$0"..U.
  205. 0x03, 0x13, 0x1b, 0x53, 0x63, 0x68, 0x61, 0x6e, // ...Schan
  206. 0x6e, 0x65, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, // nel Test
  207. 0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
  208. 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, // hority0.
  209. 0x17, 0x0d, 0x39, 0x38, 0x31, 0x31, 0x32, 0x35, // ..981125
  210. 0x32, 0x31, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x17, // 214554Z.
  211. 0x0d, 0x33, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, // .3912312
  212. 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x26, // 35959Z0&
  213. 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, // 1$0"..U.
  214. 0x03, 0x13, 0x1b, 0x53, 0x63, 0x68, 0x61, 0x6e, // ...Schan
  215. 0x6e, 0x65, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, // nel Test
  216. 0x20, 0x53, 0x47, 0x43, 0x20, 0x41, 0x75, 0x74, // SGC Aut
  217. 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x5c, // hority0.
  218. 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, // 0...*.H.
  219. 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, // ........
  220. 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xd1, // K.0H.A..
  221. 0x95, 0x8e, 0x14, 0xc9, 0x8b, 0x28, 0x00, 0xd4, // .....(..
  222. 0xed, 0x40, 0xb5, 0xd4, 0xec, 0x1f, 0x67, 0xb1, // [email protected].
  223. 0xa2, 0xb3, 0x18, 0xca, 0x6b, 0x48, 0x6c, 0x54, // ....kHlT
  224. 0xaf, 0xc4, 0x70, 0x3c, 0x6e, 0xee, 0x15, 0xba, // ..p<n...
  225. 0x4b, 0xf7, 0x40, 0x93, 0xd3, 0x35, 0x1d, 0x17, // [email protected]..
  226. 0x6c, 0xe8, 0x1d, 0x62, 0xec, 0x74, 0x96, 0x48, // l..b.t.H
  227. 0x4f, 0x1e, 0xcf, 0xf0, 0x54, 0x2b, 0x30, 0x0b, // O...T+0.
  228. 0x66, 0x3a, 0x83, 0x1c, 0x32, 0xda, 0x3d, 0x02, // f:..2.=.
  229. 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x8d, 0x30, // .......0
  230. 0x81, 0x8a, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x1d, // ..0...U.
  231. 0x0a, 0x04, 0x06, 0x30, 0x04, 0x03, 0x02, 0x07, // ...0....
  232. 0x80, 0x30, 0x20, 0x06, 0x03, 0x55, 0x1d, 0x25, // .0 ..U.%
  233. 0x04, 0x19, 0x30, 0x17, 0x06, 0x0a, 0x2b, 0x06, // ..0...+.
  234. 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x03, // ....7...
  235. 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, // ..`.H...
  236. 0x42, 0x04, 0x01, 0x30, 0x57, 0x06, 0x03, 0x55, // B..0W..U
  237. 0x1d, 0x01, 0x04, 0x50, 0x30, 0x4e, 0x80, 0x10, // ...P0N..
  238. 0x35, 0x2f, 0x90, 0xa8, 0x13, 0xd6, 0x82, 0x32, // 5......2
  239. 0x85, 0x1a, 0x5d, 0x0f, 0xdc, 0x83, 0xe3, 0x28, // ..]....(
  240. 0xa1, 0x28, 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, // .(0&1$0"
  241. 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x53, // ..U....S
  242. 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, // channel
  243. 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x47, 0x43, // Test SGC
  244. 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, // Authori
  245. 0x74, 0x79, 0x82, 0x10, 0x46, 0xeb, 0x72, 0x4f, // ty..F.rO
  246. 0xc0, 0x00, 0x78, 0xab, 0x11, 0xd2, 0x84, 0xb0, // ..x.....
  247. 0x35, 0xb8, 0xe0, 0xb1, 0x30, 0x0d, 0x06, 0x09, // 5...0...
  248. 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, // *.H.....
  249. 0x04, 0x05, 0x00, 0x03, 0x41, 0x00, 0x65, 0x35, // ....A.e5
  250. 0x80, 0xaf, 0xa3, 0xba, 0x5d, 0x13, 0xcd, 0x86, // ....]...
  251. 0xad, 0xda, 0x06, 0xb6, 0xb3, 0x51, 0xf4, 0x71, // .....Q.q
  252. 0x4a, 0x0b, 0xd2, 0xc1, 0x91, 0x13, 0xc3, 0x0c, // J.......
  253. 0xd7, 0xb7, 0x9f, 0xa6, 0x3c, 0x04, 0xfa, 0xb7, // ....<...
  254. 0x97, 0x94, 0x64, 0xf0, 0x5b, 0xab, 0x65, 0x3b, // ..d.[.e;
  255. 0x88, 0x95, 0x59, 0x4c, 0x18, 0x11, 0xc4, 0xac, // ..YL....
  256. 0x5c, 0x6e, 0x31, 0xf0, 0xdd, 0x74, 0xc1, 0x55, // .n1..t.U
  257. 0x7e, 0x7f, 0x66, 0xf4, 0x8a, 0x57 }; // ~.f..W
  258. #endif // SGC_TEST_KEY
  259. typedef struct SGC_ROOT
  260. {
  261. CONST BYTE * pbCert;
  262. DWORD cbCert;
  263. PCCERT_CONTEXT pCertContext;
  264. } SGC_ROOT, *PSGC_ROOT;
  265. static SGC_ROOT SGCRoots[] = {
  266. { GenevaSGCRoot, sizeof(GenevaSGCRoot), NULL },
  267. { VSCLASS3ROOT, sizeof(VSCLASS3ROOT), NULL },
  268. #ifdef SGC_TEST_KEY
  269. { TestSGCRoot, sizeof(TestSGCRoot), NULL }
  270. #endif // SGC_TEST_KEY
  271. };
  272. static CONST DWORD SGCRootCount = sizeof(SGCRoots) / sizeof(SGC_ROOT);
  273. static CONST LPCSTR rgSGCExtensions[]
  274. = { szOID_SGC_NETSCAPE,
  275. szOID_SERVER_GATED_CRYPTO };
  276. static CONST CERT_ENHKEY_USAGE SGCExtensions
  277. = { sizeof(rgSGCExtensions)/sizeof(LPSTR),
  278. (LPSTR *)rgSGCExtensions };
  279. //
  280. // Load root certs
  281. //
  282. DWORD
  283. LoadSGCRoots(
  284. IN CRITICAL_SECTION *pCritSec) // must be initialized
  285. {
  286. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  287. BOOL fInCritSec = FALSE;
  288. BOOL fLoadRoots = FALSE;
  289. DWORD i;
  290. // check if the Roots are already loaded
  291. for (i = 0; i < SGCRootCount; i++)
  292. {
  293. if (SGCRoots[i].pCertContext == NULL)
  294. {
  295. fLoadRoots = TRUE;
  296. break;
  297. }
  298. }
  299. if (!fLoadRoots)
  300. {
  301. dwReturn = ERROR_SUCCESS;
  302. goto ErrorExit;
  303. }
  304. // wrap with a try since there is a critical sections in here
  305. __try
  306. {
  307. // take the critical section
  308. EnterCriticalSection(pCritSec);
  309. fInCritSec = TRUE;
  310. for (i = 0; i < SGCRootCount; i++)
  311. {
  312. if (SGCRoots[i].pCertContext == NULL)
  313. {
  314. SGCRoots[i].pCertContext = CertCreateCertificateContext(
  315. X509_ASN_ENCODING,
  316. SGCRoots[i].pbCert,
  317. SGCRoots[i].cbCert);
  318. if (NULL == SGCRoots[i].pCertContext)
  319. {
  320. dwReturn = GetLastError();
  321. goto ErrorExit;
  322. }
  323. }
  324. }
  325. }
  326. __except ( EXCEPTION_EXECUTE_HANDLER )
  327. {
  328. // ?BUGBUG? Could be resource exhaustion
  329. dwReturn = ERROR_INVALID_PARAMETER;
  330. goto ErrorExit;
  331. }
  332. dwReturn = ERROR_SUCCESS;
  333. ErrorExit:
  334. if (fInCritSec)
  335. LeaveCriticalSection(pCritSec);
  336. return dwReturn;
  337. }
  338. //
  339. // delete the public key values
  340. //
  341. void
  342. SGCDeletePubKeyValues(
  343. IN OUT BYTE **ppbKeyMod,
  344. IN OUT DWORD *pcbKeyMod,
  345. IN OUT DWORD *pdwKeyExpo)
  346. {
  347. if (*ppbKeyMod)
  348. SGCFree(*ppbKeyMod);
  349. *ppbKeyMod = NULL;
  350. *pcbKeyMod = 0;
  351. *pdwKeyExpo = 0;
  352. }
  353. //
  354. // get the public key form the cert context and assign it to the
  355. // passed in parameters
  356. //
  357. DWORD
  358. SGCAssignPubKey(
  359. IN PCCERT_CONTEXT pCertContext,
  360. IN OUT BYTE **ppbKeyMod,
  361. IN OUT DWORD *pcbKeyMod,
  362. IN OUT DWORD *pdwKeyExpo)
  363. {
  364. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  365. BLOBHEADER *pBlob = NULL;
  366. DWORD cbBlob = 0;
  367. RSAPUBKEY *pRSAPubKey;
  368. BYTE *pb;
  369. // decode the public key from the cert into a PUBLICKEYBLOB
  370. if (!CryptDecodeObject(X509_ASN_ENCODING,
  371. RSA_CSP_PUBLICKEYBLOB,
  372. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  373. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
  374. 0,
  375. NULL,
  376. &cbBlob))
  377. {
  378. dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
  379. goto ErrorExit;
  380. }
  381. pBlob = (BLOBHEADER*)SGCAlloc(cbBlob);
  382. if (NULL == pBlob)
  383. {
  384. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  385. goto ErrorExit;
  386. }
  387. if (!CryptDecodeObject(X509_ASN_ENCODING,
  388. RSA_CSP_PUBLICKEYBLOB,
  389. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  390. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
  391. 0,
  392. pBlob,
  393. &cbBlob))
  394. {
  395. dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
  396. goto ErrorExit;
  397. }
  398. pRSAPubKey = (RSAPUBKEY*)((BYTE*)pBlob + sizeof(BLOBHEADER));
  399. // delete any old public key info
  400. SGCDeletePubKeyValues(ppbKeyMod, pcbKeyMod, pdwKeyExpo);
  401. // assign public key values
  402. *pdwKeyExpo = pRSAPubKey->pubexp;
  403. *pcbKeyMod = pRSAPubKey->bitlen / 8;
  404. *ppbKeyMod = (BYTE*)SGCAlloc(*pcbKeyMod);
  405. if (NULL == *ppbKeyMod)
  406. {
  407. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  408. goto ErrorExit;
  409. }
  410. pb = (BYTE*)pRSAPubKey + sizeof(RSAPUBKEY);
  411. memcpy(*ppbKeyMod, pb, *pcbKeyMod);
  412. dwReturn = ERROR_SUCCESS;
  413. ErrorExit:
  414. if (pBlob)
  415. SGCFree(pBlob);
  416. return dwReturn;
  417. }
  418. //
  419. // check if the passed in public key matches the one in the cert
  420. //
  421. static DWORD
  422. SamePublicKey(
  423. IN PCCERT_CONTEXT pCertContext,
  424. IN BYTE *pbExchKeyMod,
  425. IN DWORD cbExchKeyMod,
  426. IN DWORD dwExchKeyExpo)
  427. {
  428. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  429. BLOBHEADER *pBlob = NULL;
  430. DWORD cbBlob = 0;
  431. RSAPUBKEY *pRSAPubKey;
  432. BYTE *pb;
  433. // decode the public key from the cert into a PUBLICKEYBLOB
  434. if (!CryptDecodeObject(X509_ASN_ENCODING,
  435. RSA_CSP_PUBLICKEYBLOB,
  436. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  437. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
  438. 0,
  439. NULL,
  440. &cbBlob))
  441. {
  442. dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
  443. goto ErrorExit;
  444. }
  445. pBlob = (BLOBHEADER*)SGCAlloc(cbBlob);
  446. if (NULL == pBlob)
  447. {
  448. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  449. goto ErrorExit;
  450. }
  451. if (!CryptDecodeObject(X509_ASN_ENCODING,
  452. RSA_CSP_PUBLICKEYBLOB,
  453. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  454. pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
  455. 0,
  456. pBlob,
  457. &cbBlob))
  458. {
  459. dwReturn = (DWORD)NTE_BAD_DATA; // ?BUGBUG? Always?
  460. goto ErrorExit;
  461. }
  462. pRSAPubKey = (RSAPUBKEY*)((BYTE*)pBlob + sizeof(BLOBHEADER));
  463. // check the length of the modulus and the exponent
  464. if (((pRSAPubKey->bitlen / 8) != cbExchKeyMod) ||
  465. (pRSAPubKey->pubexp != dwExchKeyExpo))
  466. {
  467. dwReturn = (DWORD)NTE_BAD_DATA;
  468. goto ErrorExit;
  469. }
  470. // check that the modulus values match
  471. pb = (BYTE*)pRSAPubKey + sizeof(RSAPUBKEY);
  472. if (0 != memcmp(pbExchKeyMod, pb, cbExchKeyMod))
  473. {
  474. dwReturn = (DWORD)NTE_BAD_DATA;
  475. goto ErrorExit;
  476. }
  477. dwReturn = ERROR_SUCCESS;
  478. ErrorExit:
  479. if (pBlob)
  480. SGCFree(pBlob);
  481. return dwReturn;
  482. }
  483. static DWORD
  484. ReadSgcExtensions(
  485. PCCERT_CONTEXT pCertContext)
  486. {
  487. PCERT_EXTENSION pExt;
  488. PCTL_USAGE pUsage = NULL;
  489. DWORD cbUsage;
  490. DWORD dwSGCFlags = 0;
  491. DWORD i;
  492. pExt = CertFindExtension(szOID_ENHANCED_KEY_USAGE,
  493. pCertContext->pCertInfo->cExtension,
  494. pCertContext->pCertInfo->rgExtension);
  495. if (pExt == NULL)
  496. goto cleanup;
  497. if (!CryptDecodeObject(X509_ASN_ENCODING,
  498. X509_ENHANCED_KEY_USAGE,
  499. pExt->Value.pbData,
  500. pExt->Value.cbData,
  501. 0,
  502. NULL,
  503. &cbUsage))
  504. {
  505. goto cleanup;
  506. }
  507. pUsage = (PCTL_USAGE)SGCAlloc(cbUsage);
  508. if (pUsage == NULL)
  509. goto cleanup;
  510. if (!CryptDecodeObject(X509_ASN_ENCODING,
  511. X509_ENHANCED_KEY_USAGE,
  512. pExt->Value.pbData,
  513. pExt->Value.cbData,
  514. 0,
  515. pUsage,
  516. &cbUsage))
  517. {
  518. goto cleanup;
  519. }
  520. for (i = 0; i < pUsage->cUsageIdentifier; i++)
  521. {
  522. if (0 == strcmp(pUsage->rgpszUsageIdentifier[i],
  523. szOID_SGC_NETSCAPE))
  524. {
  525. dwSGCFlags |= CRYPT_SGC;
  526. }
  527. else if (0 == strcmp(pUsage->rgpszUsageIdentifier[i],
  528. szOID_SERVER_GATED_CRYPTO))
  529. {
  530. dwSGCFlags |= CRYPT_FASTSGC | CRYPT_SGC;
  531. }
  532. }
  533. cleanup:
  534. if (pUsage)
  535. SGCFree(pUsage);
  536. return dwSGCFlags;
  537. }
  538. //+---------------------------------------------------------------------------
  539. //
  540. // Function: FindBridgeCertificate
  541. //
  542. // Synopsis: Search the specified certificate store for a valid SGC
  543. // bridge certificate.
  544. //
  545. // Arguments: [hCAStore] -- Certificate store to search. This is
  546. // typically the CA store.
  547. //
  548. // [pChainContext] -- Certificate chain for which we are finding
  549. // a bridge certificate. The bridge cert
  550. // may branch off of any certificate in the
  551. // chain.
  552. //
  553. // [pRootContext] -- Handle to baked-in SGC root certificate
  554. // (typically Geneva).
  555. //
  556. // History: 11-16-98 jbanes Created
  557. //
  558. // Notes: An SGC bridge certificate is defined as a certificate with a
  559. // SUBJECT equal to the ISSUER in one of the 'pChainContext'
  560. // certificates. To be valid, the bridge certificate must
  561. // contain at least one SGC EKU and it must chain up to a
  562. // baked-in SGC root certificate.
  563. //
  564. // Returns: TRUE if a valid SGC bridge cert was found, and FALSE
  565. // otherwise.
  566. //
  567. //----------------------------------------------------------------------------
  568. static BOOL
  569. FindBridgeCertificate(
  570. IN HCERTSTORE hCAStore,
  571. IN PCCERT_CHAIN_CONTEXT pChainContext,
  572. IN PCCERT_CONTEXT pRootContext)
  573. {
  574. PCERT_SIMPLE_CHAIN pSimpleChain;
  575. PCCERT_CONTEXT pCurrent = NULL;
  576. PCCERT_CONTEXT pCurrentCA = NULL;
  577. PCCERT_CHAIN_CONTEXT pCAChainContext = NULL;
  578. CERT_CHAIN_PARA ChainPara;
  579. CERT_TRUST_STATUS TrustStatus;
  580. BOOL fFound;
  581. DWORD i;
  582. BOOL fRet = FALSE;
  583. DWORD dwFlags;
  584. //
  585. // Enumerate all of the certificates in the CA store that contain
  586. // one of the SGC extensions.
  587. //
  588. pCurrent = NULL;
  589. for (;;)
  590. {
  591. // Find an SGC intermediate certificate.
  592. pCurrentCA = CertFindCertificateInStore(
  593. hCAStore,
  594. X509_ASN_ENCODING,
  595. CERT_FIND_OR_ENHKEY_USAGE_FLAG,
  596. CERT_COMPARE_ENHKEY_USAGE,
  597. &SGCExtensions,
  598. pCurrentCA);
  599. if (pCurrentCA == NULL)
  600. break;
  601. //
  602. // Is this CA certificate a bridge for any of the certificates in the
  603. // passed in certificate chain?
  604. //
  605. fFound = FALSE;
  606. pSimpleChain = pChainContext->rgpChain[0];
  607. for (i = 0; i < pSimpleChain->cElement; i++)
  608. {
  609. pCurrent = pSimpleChain->rgpElement[i]->pCertContext;
  610. if (ReadSgcExtensions(pCurrent) == 0)
  611. {
  612. // This certificate doesn't contain any SGC certificate
  613. // extensions, so skip the rest of this chain.
  614. break;
  615. }
  616. if (CertCompareCertificateName(X509_ASN_ENCODING,
  617. &pCurrentCA->pCertInfo->Subject,
  618. &pCurrent->pCertInfo->Issuer))
  619. {
  620. // The names match. Now check the signature.
  621. dwFlags = SGC_VERIFICATION_FLAGS;
  622. if (!CertVerifySubjectCertificateContext(pCurrent,
  623. pCurrentCA,
  624. &dwFlags))
  625. {
  626. // Error checking signature.
  627. continue;
  628. }
  629. if (dwFlags & SGC_VERIFICATION_FLAGS)
  630. {
  631. // Signature did not verify or certificate expired.
  632. continue;
  633. }
  634. fFound = TRUE;
  635. break;
  636. }
  637. }
  638. if (!fFound)
  639. continue;
  640. //
  641. // Does this CA certificate chain up to Geneva?
  642. //
  643. ZeroMemory(&ChainPara, sizeof(ChainPara));
  644. ChainPara.cbSize = sizeof(ChainPara);
  645. if (!CertGetCertificateChain(NULL,
  646. pCurrentCA,
  647. NULL,
  648. hCAStore,
  649. &ChainPara,
  650. 0,
  651. NULL,
  652. &pCAChainContext))
  653. {
  654. // Error building chain.
  655. continue;
  656. }
  657. pSimpleChain = pCAChainContext->rgpChain[0];
  658. for (i = 0; i < pSimpleChain->cElement; i++)
  659. {
  660. pCurrent = pSimpleChain->rgpElement[i]->pCertContext;
  661. // Determine if certificate is signed correctly.
  662. TrustStatus = pSimpleChain->rgpElement[i]->TrustStatus;
  663. if (0 != (TrustStatus.dwErrorStatus
  664. & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
  665. {
  666. break;
  667. }
  668. // Is issuer Geneva?
  669. if (CertCompareCertificateName(pCurrent->dwCertEncodingType,
  670. &pCurrent->pCertInfo->Issuer,
  671. &pRootContext->pCertInfo->Subject))
  672. {
  673. // Verify the signature of the current certificate using the
  674. // validated root certificate from the schannel resource.
  675. dwFlags = SGC_VERIFICATION_FLAGS;
  676. if (!CertVerifySubjectCertificateContext(pCurrent,
  677. pRootContext,
  678. &dwFlags))
  679. {
  680. break;
  681. }
  682. if (dwFlags & SGC_VERIFICATION_FLAGS)
  683. break;
  684. fRet = TRUE;
  685. goto ErrorExit;
  686. }
  687. }
  688. }
  689. ErrorExit:
  690. if (pCurrentCA)
  691. CertFreeCertificateContext(pCurrentCA);
  692. if (pCAChainContext)
  693. CertFreeCertificateChain(pCAChainContext);
  694. return fRet;
  695. }
  696. //
  697. // check if the context may be SGC enabled
  698. //
  699. DWORD
  700. SPQueryCFLevel(
  701. IN PCCERT_CONTEXT pCertContext,
  702. IN BYTE *pbExchKeyMod,
  703. IN DWORD cbExchKeyMod,
  704. IN DWORD dwExchKeyExpo,
  705. OUT DWORD *pdwSGCFlags)
  706. {
  707. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  708. DWORD i, j;
  709. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  710. CERT_CHAIN_PARA ChainPara;
  711. PCERT_SIMPLE_CHAIN pSimpleChain;
  712. CERT_TRUST_STATUS TrustStatus;
  713. HCERTSTORE hCAStore = NULL;
  714. PCCERT_CONTEXT pCurrent = NULL;
  715. PCCERT_CONTEXT pIssuer = NULL;
  716. DWORD dwFlags;
  717. DWORD dwSgcFlags;
  718. DWORD dwSts;
  719. *pdwSGCFlags = 0;
  720. //
  721. // check if the passed in public key matches the one in the cert
  722. //
  723. if (pbExchKeyMod)
  724. {
  725. dwSts = SamePublicKey(pCertContext, pbExchKeyMod,
  726. cbExchKeyMod, dwExchKeyExpo);
  727. if (ERROR_SUCCESS != dwSts)
  728. {
  729. dwReturn = dwSts;
  730. goto ErrorExit;
  731. }
  732. }
  733. //
  734. // Does the leaf certificate contain any SGC extensions?
  735. //
  736. dwSgcFlags = ReadSgcExtensions(pCertContext);
  737. if (dwSgcFlags == 0)
  738. {
  739. // No SGC extensions found.
  740. dwReturn = ERROR_SUCCESS;
  741. goto ErrorExit;
  742. }
  743. //
  744. // Build a certificate chain.
  745. //
  746. ZeroMemory(&ChainPara, sizeof(ChainPara));
  747. ChainPara.cbSize = sizeof(ChainPara);
  748. *pdwSGCFlags = 0;
  749. if (!CertGetCertificateChain(
  750. NULL,
  751. pCertContext,
  752. NULL,
  753. pCertContext->hCertStore,
  754. &ChainPara,
  755. 0,
  756. NULL,
  757. &pChainContext))
  758. {
  759. dwReturn = GetLastError();
  760. goto ErrorExit;
  761. }
  762. //
  763. // Does the leaf chain directly up to the Geneva root?
  764. //
  765. pSimpleChain = pChainContext->rgpChain[0];
  766. for (i = 0; i < pSimpleChain->cElement; i++)
  767. {
  768. pCurrent = pSimpleChain->rgpElement[i]->pCertContext;
  769. if (ReadSgcExtensions(pCurrent) == 0)
  770. {
  771. // This certificate doesn't contain any SGC certificate
  772. // extensions, so skip the rest of this chain.
  773. break;
  774. }
  775. TrustStatus = pSimpleChain->rgpElement[i]->TrustStatus;
  776. if (0 != (TrustStatus.dwErrorStatus
  777. & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
  778. {
  779. // Certificate is not signed correctly.
  780. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  781. goto ErrorExit;
  782. }
  783. // Is Geneva issuer of "pCurrent"?
  784. for (j = 0; j < SGCRootCount; j++)
  785. {
  786. dwFlags = SGC_VERIFICATION_FLAGS;
  787. if (!CertVerifySubjectCertificateContext(
  788. pCurrent,
  789. SGCRoots[j].pCertContext,
  790. &dwFlags))
  791. {
  792. continue;
  793. }
  794. if (dwFlags & SGC_VERIFICATION_FLAGS)
  795. {
  796. continue;
  797. }
  798. // We made it, so set the SGC flags as appropriate.
  799. *pdwSGCFlags |= dwSgcFlags;
  800. dwReturn = ERROR_SUCCESS;
  801. goto ErrorExit;
  802. }
  803. }
  804. //
  805. // Search for bridge certificate.
  806. //
  807. hCAStore = CertOpenSystemStore(0, "CA");
  808. if (NULL == hCAStore)
  809. {
  810. dwReturn = GetLastError();
  811. goto ErrorExit;
  812. }
  813. for (i = 0; i < SGCRootCount; i++)
  814. {
  815. if (SGCRoots[i].pCertContext != NULL)
  816. {
  817. if (FindBridgeCertificate(hCAStore,
  818. pChainContext,
  819. SGCRoots[i].pCertContext))
  820. {
  821. // We made it, so set the SGC flags as appropriate.
  822. *pdwSGCFlags |= dwSgcFlags;
  823. dwReturn = ERROR_SUCCESS;
  824. goto ErrorExit;
  825. }
  826. }
  827. }
  828. dwReturn = (DWORD)NTE_FAIL;
  829. ErrorExit:
  830. if (pIssuer)
  831. CertFreeCertificateContext(pIssuer);
  832. if (pChainContext)
  833. CertFreeCertificateChain(pChainContext);
  834. if (hCAStore)
  835. CertCloseStore(hCAStore, 0);
  836. return dwReturn;
  837. }