This file contains code for validating certificates using Window's Crypt32 API, rather than OpenSSL. It's intended to go hand-in-hand with my proposed changes to cryptography that will make these bindings accessible, and will later be productised in the certitude module.
Last active
February 24, 2016 12:06
-
-
Save Lukasa/dc754d2193c53fdecde2 to your computer and use it in GitHub Desktop.
Validate certificates on Windows using Crypt32.dll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from cryptography.hazmat.bindings.crypt32.binding import lib, ffi | |
# Raw DER encoded certs. Used for testing purposes only. | |
CERTS = [ | |
b'0\x82\x04\xed0\x82\x03\xd5\xa0\x03\x02\x01\x02\x02\x10<\x9b\xfd6\xbelQ\xea\xaf!\xb8\x7f\xca\xd2\xdf\xd00\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x000_1\x0b0\t\x06\x03U\x04\x06\x13\x02FR1\x0e0\x0c\x06\x03U\x04\x08\x13\x05Paris1\x0e0\x0c\x06\x03U\x04\x07\x13\x05Paris1\x0e0\x0c\x06\x03U\x04\n\x13\x05Gandi1 0\x1e\x06\x03U\x04\x03\x13\x17Gandi Standard SSL CA 20\x1e\x17\r150916000000Z\x17\r180916235959Z0U1!0\x1f\x06\x03U\x04\x0b\x13\x18Domain Control Validated1\x1b0\x19\x06\x03U\x04\x0b\x13\x12Gandi Standard SSL1\x130\x11\x06\x03U\x04\x03\x13\ncertifi.io0\x82\x01"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\xc3\xef\xfd\x1c\x89\x88)\x887l\x1b3U\xfd\xb0fH\xdd\xa4@\x90V.J\xc6A\xd3-B\x0b\xec\x00\xd6\x16{\x04\xb3\xae\xb3\x1f\xc01\xa9/\xec\x82\xff]\x02\x96\x1d^\x07K\x9bz\x02M\x08\xa7\x1c$t\xe0\xa4*^\x8c\x11\'\xc66\x0c\x99\xb8`}y\xd1\xed2\x94~\x9e\xd3\xb8D\xafw\x1e\xac\xcb\xe5:g}\x00\xe6#\xcd\xfa\x1do\x8a\xa5\x9e\x14 j\xb4\xd5\x95\x9b\xbbN\x81U\xf1\xa0\xf9\xf4\xc8\xf4\xccC\xeb\xd8\x93m\xa8\x00\\\x06\xdb\xaf\xc1\x0b@\x9f\xf6LH\x86\xee<\xcfs\xbc\xd0~s[\x17\xd0\x9b\x85\xc7\xfa\x171\xb9L\xdfI\xc7:\xee\xf3?)\x05\xaeQ\x04\xe9\xb3\xe7b\xbc\xda\xba@1y.\xc9\x992\x9c\x91\xf1\x94o1\xbak\xdb>\xd1\x99\xc5\xb7\x87 N\xe4\xceA\xd2\xc6yy\xe9\x19\x05\\\xbf\xa0\xf9\xbfeX \xa3\xc8v^\xa2\\\xa8\x85\xdd\x16\xdb\xf8\xf5@f+S\xa7\x7f\xf0a\x87\x15\xb5\xcbN[\xfd\x8fmU\xc9\xc9\x02\x03\x01\x00\x01\xa3\x82\x01\xad0\x82\x01\xa90\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\xb3\x90\xa7\xd8\xc9\xafN\xcda<\x9f|\xad]\x7fA\xfdi0\xea0\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14f\xe0\xfa\x8de\xf6\x19Z\xc7\x9a\x94\x95T\xc7\xf1\xdfq\xdd7I0\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x05\xa00\x0c\x06\x03U\x1d\x13\x01\x01\xff\x04\x020\x000\x1d\x06\x03U\x1d%\x04\x160\x14\x06\x08+\x06\x01\x05\x05\x07\x03\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x020K\x06\x03U\x1d \x04D0B06\x06\x0b+\x06\x01\x04\x01\xb21\x01\x02\x02\x1a0\'0%\x06\x08+\x06\x01\x05\x05\x07\x02\x01\x16\x19https://cps.usertrust.com0\x08\x06\x06g\x81\x0c\x01\x02\x010A\x06\x03U\x1d\x1f\x04:0806\xa04\xa02\x860http://crl.usertrust.com/GandiStandardSSLCA2.crl0s\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04g0e0<\x06\x08+\x06\x01\x05\x05\x070\x02\x860http://crt.usertrust.com/GandiStandardSSLCA2.crt0%\x06\x08+\x06\x01\x05\x05\x070\x01\x86\x19http://ocsp.usertrust.com0%\x06\x03U\x1d\x11\x04\x1e0\x1c\x82\ncertifi.io\x82\x0ewww.certifi.io0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00r\x88&w\x9c@\xc1\xd7\xcc\x1b\xc5a\x90@\x07"\xafnB\xb8\x8e\xfc\xe6<\xef\xc7\xfb-\xb77\xb4v\x0e\xef\xa0I\xc1\xe7i/\xad\x01\xda\xc4\xa7\x86M\xfa\x00\xcd\xaa\xc1\xe2`g\xfam\x89K\x1d{U\xad\x14\x87P?\x8e\x83\xcd\xee\'\x18\x9f\xfc\xb1\xf80,!\xc6E8+B\xa3\xb2\x83\xcbQ\xd1\x87\x06\xe0\x05>\xaa\xc3\x07#\xbfP@-P\xf4i\xb3r6\x14\x01|\xcdAl\x9c\x13\xd4#o\xf09\xac\x8b\x02A\x88-\xd3\xd8\x8b\xec\x99\x0fy\xedN\xac\xad\xbd\x9a\xde~\x174*=\x90JF\x05\x00\xfd\x1a*\xd1\xf2\xe1\xdb\xd6\x94R\xcc(\x00\xfcc\xcbu\xf4q\x89\\\x91\xea\xc0l\x99\x1d\x94vy\x1c\xb8\xdf\xd1\xf0\x95Zl\xed\\&\x0e\xc7\xb2\xa9\x9e\xa7\xc8n_:\xe0\xf8\x91E\x99.\xa8~\xa6\xfe\xa4\x18\x0e\xd2\xf3\xa0\xcdS\xe4q\x05W{#\xb2\x01\x14fL-\xb1q>\xfe\xc1\xf9wz\x00g^\xde\xd0\xaa\'iW\x86\xa2\x0f\xe2O', | |
b'0\x82\x05\xe90\x82\x03\xd1\xa0\x03\x02\x01\x02\x02\x10\x05\xe4\xdc;\x948\xab;\x85\x97\xcb\xa6\xa1\x98P\xe30\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0c\x05\x000\x81\x881\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x130\x11\x06\x03U\x04\x08\x13\nNew Jersey1\x140\x12\x06\x03U\x04\x07\x13\x0bJersey City1\x1e0\x1c\x06\x03U\x04\n\x13\x15The USERTRUST Network1.0,\x06\x03U\x04\x03\x13%USERTrust RSA Certification Authority0\x1e\x17\r140912000000Z\x17\r240911235959Z0_1\x0b0\t\x06\x03U\x04\x06\x13\x02FR1\x0e0\x0c\x06\x03U\x04\x08\x13\x05Paris1\x0e0\x0c\x06\x03U\x04\x07\x13\x05Paris1\x0e0\x0c\x06\x03U\x04\n\x13\x05Gandi1 0\x1e\x06\x03U\x04\x03\x13\x17Gandi Standard SSL CA 20\x82\x01"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\x94\x04-\xa6y\x95t\xff\xd5\x00<\xf5\xae\xd8\x94\xb1)|\xc0\x8f\x0b\x0b\x89\xb9\x82\x83\x97n7(\xf5\xa2\x1a\xcf\xd2\x92\x0b\x9b\xa8\xd3\x87\x94s\x84\x10\x9f\xdc5\xcb\xc2-\x92\xac!\xb9\xcb;\xfc@\xc1\xc1\x83!\xf0\xbf\xf8\xf6\x9c\xfa\x9c\x82\x10\xc0\xd0\x8eN\xe5\rL\xb0\x91\\\x90\xb4\xa4@Q\x16\xda\xe4\x84\x12-\x05\\\xa1\x1f\x17\x19$Q\xaaz\xea\xe1\x07\x1b\x86\x8d\x01r\xf2\xe7\xd4\x83#9\x9e\xe0\xe1L\x1fk"\xa3\xb4\x10f\xb0\xed\x82\x96\xd7nj\xb4\xf2?\xb5B\xfc\xdd\x8a\xb5\xab\xba-\x1d:u\x9b1\xdc>\x9d\xac[\xd3A\rl\xb0\x1b\xf5:\xf5y\xea!\xa2\xf8\xf43RK$-\x1e\xa4\x99\xb1mH\xbc\xb8\x12\xferp|\xf7\xfb\x02u\xf4\x8d\xde\xd6\xda\xc0\xa02\x1aR\xdf8k.E8??\x04\x96\x00\xfd\xa1\xf4\xa2\xbb\xd5\x17\xd6\'|\x1bXY\x95^\x8a\x12\xfd\x9c\xab\x81>R(HQ\x85k\xf3\x91\xb2\x86?)\xb5n\x03b\xee\xd6\x05\x02\x03\x01\x00\x01\xa3\x82\x01u0\x82\x01q0\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14Sy\xbfZ\xaa+J\xcfT\x80\xe1\xd8\x9b\xc0\x9d\xf2\xb2\x03f\xcb0\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14\xb3\x90\xa7\xd8\xc9\xafN\xcda<\x9f|\xad]\x7fA\xfdi0\xea0\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x860\x12\x06\x03U\x1d\x13\x01\x01\xff\x04\x080\x06\x01\x01\xff\x02\x01\x000\x1d\x06\x03U\x1d%\x04\x160\x14\x06\x08+\x06\x01\x05\x05\x07\x03\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x020"\x06\x03U\x1d \x04\x1b0\x190\r\x06\x0b+\x06\x01\x04\x01\xb21\x01\x02\x02\x1a0\x08\x06\x06g\x81\x0c\x01\x02\x010P\x06\x03U\x1d\x1f\x04I0G0E\xa0C\xa0A\x86?http://crl.usertrust.com/USERTrustRSACertificationAuthority.crl0v\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04j0h0?\x06\x08+\x06\x01\x05\x05\x070\x02\x863http://crt.usertrust.com/USERTrustRSAAddTrustCA.crt0%\x06\x08+\x06\x01\x05\x05\x070\x01\x86\x19http://ocsp.usertrust.com0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0c\x05\x00\x03\x82\x02\x01\x00Xg\xfdr\xb2j\xd7|a\x96\x19~\xd9CF\xd1&}\xc8S\xfaf\xb0k-\xa7\xd3\xaaV\xf7:\x88\xd0;r\xc9P\xfd\xf7Y\xb2\xaah\xf5\x8cs\x03\xbb\x95e\x17\xce/\x1c\xdd\x98\x13\xa2\x91\xc9\xee\xa1@n<\x98\xd6\\\xf3\xb2"<-\xee\x1b\xa4\xe1\xde $\x16\xf2\x8c\x11s\x91:\xf6\xfa\xce$\x02\x87\xca\x93\xec\xb4\xb6\xc8\x16\x17\xc5r\xfc\'@\xf6\x13\xfe\x93\xa6\x9dQ\xef<+\xd8wW\x9b\x8ce:5%6\xb7\xb5\x8aco\x07\'\x93\xb1`\x8d\x80\xdb\x96\xd4z\x8f-\xab\x1c\x88\xc9n~\xd6e\x1f\xaf]\xca\x16?(F\xdc\xa05\xe5\xf9\xe9\xe5\xd5\x96\x88\x0cO\xc6\xb7wgH\x84\'\xb6\x1f\xb0h\xdb\xac\xbfw\xb0\x90\xb8\xa2\xc9\x1c2]\x02\xba%C\x81BG\xbb\xd8\xe1\x8f\x0c\x0cF_\xeeF3k\x03\x14\x82\xd3~\xcd\x8f\xaf\x90\xd6\x8e$}@B\xb4jj\x17\xc6\x95\x97\xe1\xf28\xcd\xa7\xed\xb4\'@\x93\xdfr\xa9\xb8\xc6fc78d"0\xa2;\xf1\xb9\xc8{\xc8\xfb):\xab\x1ar\xd2\x06\x12N\xf6\x82\xd4#o>\xc3\x93\xe5\xd8\xb6\xc0\xde\xdc#\x16\xd6\x130\xb7\xa0\x9a\x0e,U\x06\x00p\x01\xcf\xea9\x1d\x80\xdb\x88\xf7\xa5 \xb8[\xfd1&i\x8f-\na\x83:G\xa6\x13T,\x1e\xe3\xedD\xca\xbcj\x1f(\x0eQ\xd9\xde\x0e\x9fu\xcd\x0e\x03\x95\xca\xf9\xc5\xa9*-\xfeA\xa4\xa1G\xae\r\xc2\xf99f3J[\xe1\x84(Yl}\x94\x17v\xe4E\x82\xadp \xfd\xd2oc\xa8\xd7\xfa\xa03\xfa7\xcb\xf7\xb2e\x9e\xdaPo?\xe4\xa7\xf3\x8e]X2\x97p#.\xe7\xfd\xc4\x15\x9b\x9c\'\x8f2\xed\x17\xadX\x811)\x11\x1a\x9b\xd4\xfcl\x95(\xc7N\x05\x07\xa6\xfd\x1d\xbc\x19\xe2\xe8\xb7\xb9\x11\x8a-p\x12R\x85\x8d\x8c3J\x0f\xfc\x99\x92\xe0cp\xda\xa5\x94Gc\x07\xe7X\xc71_\x05=6U\xfe\x83\xb2\xe8\xa6\xad\xd7\xe9\xe6\x02t\x88t\\\xda4\xdb\x90\xd2mQ\n#\xd6#', | |
b'0\x82\x05w0\x82\x04_\xa0\x03\x02\x01\x02\x02\x10\x13\xea(p[\xf4\xec\xed\x0c6c\t\x80aC60\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0c\x05\x000o1\x0b0\t\x06\x03U\x04\x06\x13\x02SE1\x140\x12\x06\x03U\x04\n\x13\x0bAddTrust AB1&0$\x06\x03U\x04\x0b\x13\x1dAddTrust External TTP Network1"0 \x06\x03U\x04\x03\x13\x19AddTrust External CA Root0\x1e\x17\r000530104838Z\x17\r200530104838Z0\x81\x881\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x130\x11\x06\x03U\x04\x08\x13\nNew Jersey1\x140\x12\x06\x03U\x04\x07\x13\x0bJersey City1\x1e0\x1c\x06\x03U\x04\n\x13\x15The USERTRUST Network1.0,\x06\x03U\x04\x03\x13%USERTrust RSA Certification Authority0\x82\x02"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\x80\x12e\x176\x0e\xc3\xdb\x08\xb3\xd0\xacW\rv\xed\xcd\'\xd3L\xadP\x83a\xe2\xaa M\t-d\t\xdc\xce\x89\x9f\xcc=\xa9\xec\xf6\xcf\xc1\xdc\xf1\xd3\xb1\xd6{7(\x11+G\xda9\xc6\xbc:\x19\xb4_\xa6\xbd}\x9d\xa3cB\xb6v\xf2\xa9;+\x91\xf8\xe2o\xd0\xec\x16 \x90\t>\xe2\xe8t\xc9\x18\xb4\x91\xd4bd\xdb\x7f\xa3\x06\xf1\x88\x18j\x90"<\xbc\xfe\x13\xf0\x87\x14{\xf6\xe4\x1f\x8e\xd4\xe4Q\xc6\x11gF\x08Q\xcb\x86\x14T?\xbc3\xfe~l\x9c\xff\x16\x9d\x18\xbdQ\x8e5\xa6\xa7f\xc8rg\xdb!f\xb1\xd4\x9bx\x03\xc0P:\xe8\xcc\xf0\xdc\xbc\x9eL\xfe\xaf\x05\x965\x1fWZ\xb7\xff\xce\xf9=\xb7,\xb6\xf6T\xdd\xc8\xe7\x12:M\xaeL\x8a\xb7\\\x9a\xb4\xb7 =\xca\x7f"4\xae~;hf\x01D\xe7\x01NFS\x9b3`\xf7\x94\xbeS7\x90sC\xf32\xc3S\xef\xdb\xaa\xfetNi\xc7k\x8c`\x93\xde\xc4\xc7\x0c\xdf\xe12\xae\xcc\x93;Qx\x95g\x8b\xee=V\xfe\x0c\xd0i\x0f\x1b\x0f\xf3%&k3m\xf7nG\xfasC\xe5~\x0e\xa5f\xb1)|2\x84cU\x89\xc4\r\xc1\x93T0\x19\x13\xac\xd3}7\xa7\xeb]:l5\\\xdbA\xd7\x12\xda\xa9I\x0b\xdf\xd8\x80\x8a\t\x93b\x8e\xb5f\xcf%\x88\xcd\x84\xb8\xb1?\xa49\x0f\xd9\x02\x9e\xeb\x12L\x95|\xf3k\x05\xa9^\x16\x83\xcc\xb8g\xe2\xe8\x13\x9d\xcc[\x82\xd3L\xb3\xed[\xff\xde\xe5s\xac#;-\x00\xbf5Ut\tI\xd8IX\x1a\x7f\x926\xe6Q\x92\x0e\xf3&}\x1cM\x17\xbc\xc9\xecC&\xd0\xbfA_@\xa9DD\xf4\x99\xe7W\x87\x9eP\x1fWT\xa8>\xfdtc/\xb1Pe\t\xe6XB.C\x1aL\xb4\xf0%GY\xfa\x04\x1e\x93\xd4&FJP\x81\xb2\xde\xbex\xb7\xfcg\x15\xe1\xc9W\x84\x1e\x0fc\xd6\xe9b\xba\xd6_U.\xea\\\xc6(\x08\x04%9\xb8\x0e+\xa9\xf2L\x97\x1c\x07?\rR\xf5\xed\xef/\x82\x0f\x02\x03\x01\x00\x01\xa3\x81\xf40\x81\xf10\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\xad\xbd\x98z4\xb4&\xf7\xfa\xc4&T\xef\x03\xbd\xe0$\xcbT\x1a0\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14Sy\xbfZ\xaa+J\xcfT\x80\xe1\xd8\x9b\xc0\x9d\xf2\xb2\x03f\xcb0\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x860\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff0\x11\x06\x03U\x1d \x04\n0\x080\x06\x06\x04U\x1d \x000D\x06\x03U\x1d\x1f\x04=0;09\xa07\xa05\x863http://crl.usertrust.com/AddTrustExternalCARoot.crl05\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04)0\'0%\x06\x08+\x06\x01\x05\x05\x070\x01\x86\x19http://ocsp.usertrust.com0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0c\x05\x00\x03\x82\x01\x01\x00\x93e\xf67\x83\x95\x0f^\xc3\x82\x1c\x1f\xd6w\xe7<\x8a\xc0\xaa\t\xf0\xe9\x0b&\xf1\xe0\xc2ju\xa1\xc7y\xc9\xb9R`\xc8)\x12\x0e\xf0\xad\x03\xd6\t\xc4v\xdf\xe5\xa6\x81\x95\xa7F\xda\x82W\xa9\x95\x92\xc5\xb6\x8f\x03"l3w\xc1{2\x17n\x07\xceZ\x14A:\x05$\x1b\xf6\x14\x06;\xa8%$\x0e\xbb\xcc*u\xdd\xb9pA?|\xd0c6!\x07\x1fF\xff`\xa4\x91\xe1g\xbc\xde\x1f~\x19\x14\xc9cg\x91\xeag\x07k\xb4\x8f\x8b\xc0nC}\xc3\xa1\x80l\xb2\x1e\xbcS\x85}\xdc\x90\xa1\xa4\xbc-\xefFrW5\x05\xbf\xbbF\xbbnm7\x99\xb6\xff#\x92\x91\xc6n@\xf8\x8f)V\xea_\xd5_\x14S\xac\xf0Oa\xea\xf7"\xcc\xa7V\x0b\xe2\xb84\x1f&\xd9{\x19\x05h?\xba<\xd48\x06\xa2\xd3\xe6\x8f\x0e\xe3\xb4qm@B\xc5\x84\xb4@\x95+\xf4e\xa0Hy\xf6\x1d\x81c\x96\x9dOu\xe0\xf8|\xe4\x8e\xa9\xd1\xf2\xad\x8a\xb3\x8c\xc7!\xcd\xc2\xef', | |
] | |
SERVER_NAME = u"certifi.io" | |
def build_certificate_context(certs): | |
""" | |
Builds a Windows certificate context from a list of DER-encoded certs. | |
""" | |
store = lib.CertOpenStore( | |
lib.CERT_STORE_PROV_MEMORY, | |
0, | |
ffi.NULL, | |
lib.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, | |
ffi.NULL | |
) | |
assert store | |
store = ffi.gc(store, lambda s: lib.CertCloseStore(s, 0)) | |
primary_cert = ffi.new("PCCERT_CONTEXT *") | |
ok = lib.CertAddEncodedCertificateToStore( | |
store, | |
lib.X509_ASN_ENCODING, | |
certs[0], | |
len(certs[0]), | |
lib.CERT_STORE_ADD_ALWAYS, | |
primary_cert | |
) | |
assert ok and primary_cert[0] | |
primary_cert = ffi.gc(primary_cert, lambda x: lib.CertFreeCertificateContext(x[0])) | |
for cert in certs[1:]: | |
ok = lib.CertAddEncodedCertificateToStore( | |
store, | |
lib.X509_ASN_ENCODING, | |
cert, | |
len(cert), | |
lib.CERT_STORE_ADD_ALWAYS, | |
ffi.NULL | |
) | |
assert ok | |
return primary_cert | |
def test(): | |
assert isinstance(SERVER_NAME, str) # We need a unicode string here. | |
cert = build_certificate_context(CERTS) | |
# First, we need to build a certificate chain. This gets Windows | |
# to see if it can build a chain at all: it says nothing about | |
# whether the chain is acceptable in this case (e.g. for this | |
# host). | |
chain_para = ffi.new("CERT_CHAIN_PARA *") | |
chain_para[0].cbSize = ffi.sizeof(chain_para[0]) | |
# Extended key usage. We still need to request | |
# SERVER_GATED_CRYPTO and NETSCAPE because...well, | |
# because Chrome and IE do. | |
usage = ffi.new( | |
"LPCSTR[]", | |
[ | |
lib.szOID_PKIX_KP_SERVER_AUTH, | |
lib.szOID_SERVER_GATED_CRYPTO, | |
lib.szOID_SGC_NETSCAPE, | |
] | |
) | |
chain_para[0].RequestedUsage.dwType = lib.USAGE_MATCH_TYPE_OR | |
chain_para[0].RequestedUsage.Usage.cUsageIdentifier = 3 # TODO: Programmatically set this! | |
chain_para[0].RequestedUsage.Usage.rgpszUsageIdentifier = usage | |
#import pdb; pdb.set_trace() | |
chain_context = ffi.new("PCCERT_CHAIN_CONTEXT *") | |
got_chain = lib.CertGetCertificateChain( | |
ffi.NULL, # chain_engine | |
cert[0], # certificate | |
ffi.NULL, # current system time | |
cert[0][0].hCertStore, # Certificate store | |
chain_para, # Chain parameters | |
0, # No flags | |
ffi.NULL, # Reserved | |
chain_context, | |
) | |
assert got_chain | |
assert chain_context[0] | |
chain_context = ffi.gc(chain_context, lambda s: lib.CertFreeCertificateChain(s[0])) | |
# Next, we need to check that the chain meets our "policy". This is basically: | |
# is the chain valid for the server in question over TLS? | |
server_name = ffi.new("wchar_t[]", SERVER_NAME) | |
extra_policy_para = ffi.new("SSL_EXTRA_CERT_CHAIN_POLICY_PARA *") | |
extra_policy_para[0].cbSize = ffi.sizeof(extra_policy_para[0]) | |
extra_policy_para[0].dwAuthType = lib.AUTHTYPE_SERVER | |
extra_policy_para[0].fdwChecks = 0 | |
extra_policy_para[0].pwszServerName = server_name # MUST BE UNICODE | |
policy_para = ffi.new("CERT_CHAIN_POLICY_PARA *") | |
policy_para[0].cbSize = ffi.sizeof(policy_para[0]) | |
policy_para[0].dwFlags = 0 | |
policy_para[0].pvExtraPolicyPara = extra_policy_para | |
policy_status = ffi.new("CERT_CHAIN_POLICY_STATUS *") | |
policy_status[0].cbSize = ffi.sizeof(policy_status[0]) | |
policy_exists = lib.CertVerifyCertificateChainPolicy( | |
lib.CERT_CHAIN_POLICY_SSL, | |
chain_context[0], | |
policy_para, | |
policy_status | |
) | |
assert policy_exists | |
# TODO: This is probably overbroad. Look at the errors in https://msdn.microsoft.com/en-us/library/windows/desktop/aa377188(v=vs.85).aspx | |
# and re-evaluate. | |
assert not policy_status[0].dwError | |
test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment