ruby-changes:43348
From: rhe <ko1@a...>
Date: Wed, 15 Jun 2016 19:52:42 +0900 (JST)
Subject: [ruby-changes:43348] rhe:r55422 (trunk): openssl: allow specifying hash algorithm in OCSP::*#sign
rhe 2016-06-15 19:52:37 +0900 (Wed, 15 Jun 2016) New Revision: 55422 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55422 Log: openssl: allow specifying hash algorithm in OCSP::*#sign * ext/openssl/ossl_ocsp.c (ossl_ocspreq_sign, ossl_ocspbres_sign): Allow specifying hash algorithm used in signing. They are hard coded to use SHA-1. Based on a patch provided by Tim Shirley <tidoublemy@g...>. [ruby-core:70915] [Feature #11552] [GH ruby/openssl#28] * test/openssl/test_ocsp.rb: Test sign-verify works. Modified files: trunk/ChangeLog trunk/ext/openssl/ossl_ocsp.c trunk/test/openssl/test_ocsp.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 55421) +++ ChangeLog (revision 55422) @@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed Jun 15 19:52:23 2016 Kazuki Yamaguchi <k@r...> + + * ext/openssl/ossl_ocsp.c (ossl_ocspreq_sign, ossl_ocspbres_sign): Allow + specifying hash algorithm used in signing. They are hard coded to use + SHA-1. + Based on a patch provided by Tim Shirley <tidoublemy@g...>. + [ruby-core:70915] [Feature #11552] [GH ruby/openssl#28] + + * test/openssl/test_ocsp.rb: Test sign-verify works. + Wed Jun 15 01:46:16 2016 Nobuyoshi Nakada <nobu@r...> * numeric.c: [DOC] fix rdoc directive, and an example of negative Index: test/openssl/test_ocsp.rb =================================================================== --- test/openssl/test_ocsp.rb (revision 55421) +++ test/openssl/test_ocsp.rb (revision 55422) @@ -86,14 +86,34 @@ class OpenSSL::TestOCSP < OpenSSL::TestC https://github.com/ruby/ruby/blob/trunk/test/openssl/test_ocsp.rb#L86 assert_equal asn1.to_der, OpenSSL::OCSP::Request.new(asn1.to_der).to_der end - def test_new_ocsp_request + def test_request_sign_verify request = OpenSSL::OCSP::Request.new cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) request.add_certid(cid) - request.sign(@cert, @key, [@cert]) - assert_kind_of OpenSSL::OCSP::Request, request - # in current implementation not same instance of certificate id, but should contain same data - assert_equal cid.serial, request.certid.first.serial + request.sign(@cert, @key, nil, 0, "SHA1") + assert_equal cid.to_der, request.certid.first.to_der + store1 = OpenSSL::X509::Store.new; store1.add_cert(@ca_cert) + assert_equal true, request.verify([@cert], store1) + assert_equal true, request.verify([], store1) + store2 = OpenSSL::X509::Store.new; store1.add_cert(@cert2) + assert_equal false, request.verify([], store2) + assert_equal true, request.verify([], store2, OpenSSL::OCSP::NOVERIFY) + end + + def test_request_nonce + req0 = OpenSSL::OCSP::Request.new + req1 = OpenSSL::OCSP::Request.new + req1.add_nonce("NONCE") + req2 = OpenSSL::OCSP::Request.new + req2.add_nonce("NONCF") + bres = OpenSSL::OCSP::BasicResponse.new + assert_equal 2, req0.check_nonce(bres) + bres.copy_nonce(req1) + assert_equal 1, req1.check_nonce(bres) + bres.add_nonce("NONCE") + assert_equal 1, req1.check_nonce(bres) + assert_equal 0, req2.check_nonce(bres) + assert_equal 3, req0.check_nonce(bres) end def test_basic_response_der @@ -109,6 +129,18 @@ class OpenSSL::TestOCSP < OpenSSL::TestC https://github.com/ruby/ruby/blob/trunk/test/openssl/test_ocsp.rb#L129 assert_equal der, OpenSSL::OCSP::BasicResponse.new(der).to_der end + def test_basic_response_sign_verify + cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA256.new) + bres = OpenSSL::OCSP::BasicResponse.new + bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, -400, -300, 500, []) + bres.sign(@cert2, @key2, [], 0, "SHA256") # how can I check the algorithm? + store1 = OpenSSL::X509::Store.new; store1.add_cert(@ca_cert) + assert_equal true, bres.verify([], store1) + store2 = OpenSSL::X509::Store.new; store2.add_cert(@cert) + assert_equal false, bres.verify([], store2) + assert_equal true, bres.verify([], store2, OpenSSL::OCSP::NOVERIFY) + end + def test_response_der bres = OpenSSL::OCSP::BasicResponse.new cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new) Index: ext/openssl/ossl_ocsp.c =================================================================== --- ext/openssl/ossl_ocsp.c (revision 55421) +++ ext/openssl/ossl_ocsp.c (revision 55422) @@ -312,39 +312,48 @@ ossl_ocspreq_get_certid(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ocsp.c#L312 /* * call-seq: - * request.sign(signer_cert, signer_key) -> self - * request.sign(signer_cert, signer_key, certificates) -> self - * request.sign(signer_cert, signer_key, certificates, flags) -> self - * - * Signs this OCSP request using +signer_cert+ and +signer_key+. - * +certificates+ is an optional Array of certificates that may be included in - * the request. + * request.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self + * + * Signs this OCSP request using +cert+, +key+ and optional +digest+. If + * +digest+ is not specified, SHA-1 is used. +certs+ is an optional Array of + * additional certificates that will be included in the request. If +certs+ is + * not specified, flag OpenSSL::OCSP::NOCERTS is set. Pass an empty array to + * include only the signer certificate. + * + * +flags+ can include: + * OpenSSL::OCSP::NOCERTS:: don't include certificates */ static VALUE ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) { - VALUE signer_cert, signer_key, certs, flags; + VALUE signer_cert, signer_key, certs, flags, digest; OCSP_REQUEST *req; X509 *signer; EVP_PKEY *key; - STACK_OF(X509) *x509s; - unsigned long flg; + STACK_OF(X509) *x509s = NULL; + unsigned long flg = 0; + const EVP_MD *md; int ret; - rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); + rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest); + GetOCSPReq(self, req); signer = GetX509CertPtr(signer_cert); key = GetPrivPKeyPtr(signer_key); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - if(NIL_P(certs)){ - x509s = sk_X509_new_null(); + if (!NIL_P(flags)) + flg = NUM2INT(flags); + if (NIL_P(digest)) + md = EVP_sha1(); + else + md = GetDigestPtr(digest); + if (NIL_P(certs)) flags |= OCSP_NOCERTS; - } - else x509s = ossl_x509_ary2sk(certs); - GetOCSPReq(self, req); - ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg); + else + x509s = ossl_x509_ary2sk(certs); + + ret = OCSP_request_sign(req, signer, key, md, x509s, flg); sk_X509_pop_free(x509s, X509_free); - if(!ret) ossl_raise(eOCSPError, NULL); + if (!ret) ossl_raise(eOCSPError, NULL); return self; } @@ -799,40 +808,47 @@ ossl_ocspbres_get_status(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ocsp.c#L808 /* * call-seq: - * basic_response.sign(signer_cert, signer_key) -> self - * basic_response.sign(signer_cert, signer_key, certificates) -> self - * basic_response.sign(signer_cert, signer_key, certificates, flags) -> self + * basic_response.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self * - * Signs this response using the +signer_cert+ and +signer_key+. Additional - * +certificates+ may be added to the signature along with a set of +flags+. + * Signs this OCSP response using the +cert+, +key+ and optional +digest+. This + * behaves in the similar way as OpenSSL::OCSP::Request#sign. + * + * +flags+ can include: + * OpenSSL::OCSP::NOCERTS:: don't include certificates + * OpenSSL::OCSP::NOTIME:: don't set producedAt + * OpenSSL::OCSP::RESPID_KEY:: use signer's public key hash as responderID */ static VALUE ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) { - VALUE signer_cert, signer_key, certs, flags; + VALUE signer_cert, signer_key, certs, flags, digest; OCSP_BASICRESP *bs; X509 *signer; EVP_PKEY *key; - STACK_OF(X509) *x509s; - unsigned long flg; + STACK_OF(X509) *x509s = NULL; + unsigned long flg = 0; + const EVP_MD *md; int ret; - rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); + rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest); + GetOCSPBasicRes(self, bs); signer = GetX509CertPtr(signer_cert); key = GetPrivPKeyPtr(signer_key); - flg = NIL_P(flags) ? 0 : NUM2INT(flags); - if(NIL_P(certs)){ - x509s = sk_X509_new_null(); + if (!NIL_P(flags)) + flg = NUM2INT(flags); + if (NIL_P(digest)) + md = EVP_sha1(); + else + md = GetDigestPtr(digest); + if (NIL_P(certs)) flg |= OCSP_NOCERTS; - } - else{ + else x509s = ossl_x509_ary2sk(certs); - } - GetOCSPBasicRes(self, bs); - ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg); + + ret = OCSP_basic_sign(bs, signer, key, md, x509s, flg); sk_X509_pop_free(x509s, X509_free); - if(!ret) ossl_raise(eOCSPError, NULL); + if (!ret) ossl_raise(eOCSPError, NULL); return self; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/