Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: net/tools/testserver/minica.py

Issue 2040513003: Implement Expect-Staple (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move OCSP into cert_verify_proc Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import asn1 5 import asn1
6 import datetime
6 import hashlib 7 import hashlib
7 import os 8 import os
9 import time
8 10
11 GENERALIZED_TIME_FORMAT = "%Y%m%d%H%M%SZ"
12
13 OCSP_STATE_GOOD = 1
14 OCSP_STATE_REVOKED = 2
15 OCSP_STATE_INVALID = 3
16 OCSP_STATE_UNAUTHORIZED = 4
17 OCSP_STATE_UNKNOWN = 5
18
19 OCSP_DATE_VALID = 1
20 OCSP_DATE_OLD = 2
21 OCSP_DATE_YOUNG = 3
22 OCSP_DATE_LONG = 4
9 23
10 # This file implements very minimal certificate and OCSP generation. It's 24 # This file implements very minimal certificate and OCSP generation. It's
11 # designed to test revocation checking. 25 # designed to test revocation checking.
12 26
13 def RandomNumber(length_in_bytes): 27 def RandomNumber(length_in_bytes):
14 '''RandomNumber returns a random number of length 8*|length_in_bytes| bits''' 28 '''RandomNumber returns a random number of length 8*|length_in_bytes| bits'''
15 rand = os.urandom(length_in_bytes) 29 rand = os.urandom(length_in_bytes)
16 n = 0 30 n = 0
17 for x in rand: 31 for x in rand:
18 n <<= 8 32 n <<= 8
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 252
239 return asn1.ToDER(asn1.SEQUENCE([ 253 return asn1.ToDER(asn1.SEQUENCE([
240 asn1.Raw(tbsCert), 254 asn1.Raw(tbsCert),
241 asn1.SEQUENCE([ 255 asn1.SEQUENCE([
242 SHA256_WITH_RSA_ENCRYPTION, 256 SHA256_WITH_RSA_ENCRYPTION,
243 None, 257 None,
244 ]), 258 ]),
245 asn1.BitString(privkey.Sign(tbsCert)), 259 asn1.BitString(privkey.Sign(tbsCert)),
246 ])) 260 ]))
247 261
248 262 def MakeOCSPResponse(issuer_cn, issuer_key, serial, ocsp_state, ocsp_date):
249 def MakeOCSPResponse(issuer_cn, issuer_key, serial, ocsp_state):
250 # https://tools.ietf.org/html/rfc2560 263 # https://tools.ietf.org/html/rfc2560
251 issuer_name_hash = asn1.OCTETSTRING( 264 issuer_name_hash = asn1.OCTETSTRING(
252 hashlib.sha1(asn1.ToDER(Name(cn = issuer_cn))).digest()) 265 hashlib.sha1(asn1.ToDER(Name(cn = issuer_cn))).digest())
253 266
254 issuer_key_hash = asn1.OCTETSTRING( 267 issuer_key_hash = asn1.OCTETSTRING(
255 hashlib.sha1(asn1.ToDER(issuer_key)).digest()) 268 hashlib.sha1(asn1.ToDER(issuer_key)).digest())
256 269
257 cert_status = None 270 cert_status = None
258 if ocsp_state == OCSP_STATE_REVOKED: 271 if ocsp_state == OCSP_STATE_REVOKED:
259 cert_status = asn1.Explicit(1, asn1.GeneralizedTime("20100101060000Z")) 272 cert_status = asn1.Explicit(1, asn1.GeneralizedTime("20100101060000Z"))
260 elif ocsp_state == OCSP_STATE_UNKNOWN: 273 elif ocsp_state == OCSP_STATE_UNKNOWN:
261 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 2, 0)) 274 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 2, 0))
262 elif ocsp_state == OCSP_STATE_GOOD: 275 elif ocsp_state == OCSP_STATE_GOOD:
263 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 0, 0)) 276 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 0, 0))
264 else: 277 else:
265 raise ValueError('Bad OCSP state: ' + str(ocsp_state)) 278 raise ValueError('Bad OCSP state: ' + str(ocsp_state))
266 279
280 now = datetime.datetime.fromtimestamp(time.mktime(time.gmtime()))
281 if ocsp_date == OCSP_DATE_VALID:
282 thisUpdate = now - datetime.timedelta(hours=1)
283 nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
284 elif ocsp_date == OCSP_DATE_OLD:
285 thisUpdate = now - datetime.timedelta(hours=1, weeks=1)
286 nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
287 elif ocsp_date == OCSP_DATE_YOUNG:
svaldez 2016/06/23 14:03:16 EARLY?
288 thisUpdate = now + datetime.timedelta(hours=1)
289 nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
290 elif ocsp_date == OCSP_DATE_LONG:
291 thisUpdate = now - datetime.timedelta(days=365)
292 nextUpdate = thisUpdate + datetime.timedelta(hours=1, days=365)
293 else:
294 raise ValueError('Bad OCSP date: ' + str(ocsp_date))
295
267 basic_resp_data_der = asn1.ToDER(asn1.SEQUENCE([ 296 basic_resp_data_der = asn1.ToDER(asn1.SEQUENCE([
268 asn1.Explicit(2, issuer_key_hash), 297 asn1.Explicit(2, issuer_key_hash),
269 asn1.GeneralizedTime("20100101060000Z"), # producedAt 298 asn1.GeneralizedTime("20100101060000Z"), # producedAt
270 asn1.SEQUENCE([ 299 asn1.SEQUENCE([
271 asn1.SEQUENCE([ # SingleResponse 300 asn1.SEQUENCE([ # SingleResponse
272 asn1.SEQUENCE([ # CertID 301 asn1.SEQUENCE([ # CertID
273 asn1.SEQUENCE([ # hashAlgorithm 302 asn1.SEQUENCE([ # hashAlgorithm
274 HASH_SHA1, 303 HASH_SHA1,
275 None, 304 None,
276 ]), 305 ]),
277 issuer_name_hash, 306 issuer_name_hash,
278 issuer_key_hash, 307 issuer_key_hash,
279 serial, 308 serial,
280 ]), 309 ]),
281 cert_status, 310 cert_status,
282 asn1.GeneralizedTime("20100101060000Z"), # thisUpdate 311 asn1.GeneralizedTime( # thisUpdate, 1 hour ago
283 asn1.Explicit(0, asn1.GeneralizedTime("20300101060000Z")), # nextUpdate 312 thisUpdate.strftime(GENERALIZED_TIME_FORMAT)
313 ),
314 asn1.Explicit( # nextUpdate, 7 days later
315 0,
316 asn1.GeneralizedTime(nextUpdate.strftime(GENERALIZED_TIME_FORMAT))
317 ),
284 ]), 318 ]),
285 ]), 319 ]),
286 ])) 320 ]))
287 321
288 basic_resp = asn1.SEQUENCE([ 322 basic_resp = asn1.SEQUENCE([
289 asn1.Raw(basic_resp_data_der), 323 asn1.Raw(basic_resp_data_der),
290 asn1.SEQUENCE([ 324 asn1.SEQUENCE([
291 SHA256_WITH_RSA_ENCRYPTION, 325 SHA256_WITH_RSA_ENCRYPTION,
292 None, 326 None,
293 ]), 327 ]),
(...skipping 10 matching lines...) Expand all
304 338
305 return asn1.ToDER(resp) 339 return asn1.ToDER(resp)
306 340
307 341
308 def DERToPEM(der): 342 def DERToPEM(der):
309 pem = '-----BEGIN CERTIFICATE-----\n' 343 pem = '-----BEGIN CERTIFICATE-----\n'
310 pem += der.encode('base64') 344 pem += der.encode('base64')
311 pem += '-----END CERTIFICATE-----\n' 345 pem += '-----END CERTIFICATE-----\n'
312 return pem 346 return pem
313 347
314 OCSP_STATE_GOOD = 1
315 OCSP_STATE_REVOKED = 2
316 OCSP_STATE_INVALID = 3
317 OCSP_STATE_UNAUTHORIZED = 4
318 OCSP_STATE_UNKNOWN = 5
319
320 # unauthorizedDER is an OCSPResponse with a status of 6: 348 # unauthorizedDER is an OCSPResponse with a status of 6:
321 # SEQUENCE { ENUM(6) } 349 # SEQUENCE { ENUM(6) }
322 unauthorizedDER = '30030a0106'.decode('hex') 350 unauthorizedDER = '30030a0106'.decode('hex')
323 351
324 def GenerateCertKeyAndOCSP(subject = "127.0.0.1", 352 def GenerateCertKeyAndOCSP(subject = "127.0.0.1",
325 ocsp_url = "http://127.0.0.1", 353 ocsp_url = "http://127.0.0.1",
326 ocsp_state = OCSP_STATE_GOOD, 354 ocsp_state = OCSP_STATE_GOOD,
355 ocsp_date = OCSP_DATE_VALID,
327 serial = 0): 356 serial = 0):
328 '''GenerateCertKeyAndOCSP returns a (cert_and_key_pem, ocsp_der) where: 357 '''GenerateCertKeyAndOCSP returns a (cert_and_key_pem, ocsp_der) where:
329 * cert_and_key_pem contains a certificate and private key in PEM format 358 * cert_and_key_pem contains a certificate and private key in PEM format
330 with the given subject common name and OCSP URL. 359 with the given subject common name and OCSP URL.
331 * ocsp_der contains a DER encoded OCSP response or None if ocsp_url is 360 * ocsp_der contains a DER encoded OCSP response or None if ocsp_url is
332 None''' 361 None'''
333 362
334 if serial == 0: 363 if serial == 0:
335 serial = RandomNumber(16) 364 serial = RandomNumber(16)
336 cert_der = MakeCertificate(ISSUER_CN, bytes(subject), serial, KEY, KEY, 365 cert_der = MakeCertificate(ISSUER_CN, bytes(subject), serial, KEY, KEY,
337 bytes(ocsp_url)) 366 bytes(ocsp_url))
338 cert_pem = DERToPEM(cert_der) 367 cert_pem = DERToPEM(cert_der)
339 368
340 ocsp_der = None 369 ocsp_der = None
341 if ocsp_url is not None: 370 if ocsp_url is not None:
342 if ocsp_state == OCSP_STATE_UNAUTHORIZED: 371 if ocsp_state == OCSP_STATE_UNAUTHORIZED:
343 ocsp_der = unauthorizedDER 372 ocsp_der = unauthorizedDER
344 elif ocsp_state == OCSP_STATE_INVALID: 373 elif ocsp_state == OCSP_STATE_INVALID:
345 ocsp_der = '3' 374 ocsp_der = '3'
346 else: 375 else:
347 ocsp_der = MakeOCSPResponse(ISSUER_CN, KEY, serial, ocsp_state) 376 ocsp_der = MakeOCSPResponse(
377 ISSUER_CN, KEY, serial, ocsp_state, ocsp_date)
348 378
349 return (cert_pem + KEY_PEM, ocsp_der) 379 return (cert_pem + KEY_PEM, ocsp_der)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698