diff options
author | Michal Rokos <m.rokos@sh.cvut.cz> | 2002-01-04 11:12:22 +0000 |
---|---|---|
committer | Michal Rokos <m.rokos@sh.cvut.cz> | 2002-01-04 11:12:22 +0000 |
commit | 30c7790a512172b5254775fbad8f601d5638c1e6 (patch) | |
tree | 39a0ceb2db8fcd07e8b82bc107e5cc2a05df9d24 | |
parent | 99d5a24aa57c9eb4ac792a36e0947dc5df84fe8c (diff) | |
download | ruby-openssl-history-30c7790a512172b5254775fbad8f601d5638c1e6.tar.gz |
* Further checking (Check_SafeStr, memory leaks)
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | README | 282 | ||||
-rw-r--r-- | extconf.rb | 5 | ||||
-rw-r--r-- | lib/openssl.rb | 262 | ||||
-rw-r--r-- | missing/strncasecmp.c | 19 | ||||
-rw-r--r-- | missing/strptime.c | 363 | ||||
-rw-r--r-- | openssl_missing.c | 1 | ||||
-rw-r--r-- | ossl.c | 35 | ||||
-rw-r--r-- | ossl.h | 43 | ||||
-rw-r--r-- | ossl_bn.c | 334 | ||||
-rw-r--r-- | ossl_cipher.c | 60 | ||||
-rw-r--r-- | ossl_config.c | 20 | ||||
-rw-r--r-- | ossl_digest.c | 31 | ||||
-rw-r--r-- | ossl_hmac.c | 8 | ||||
-rw-r--r-- | ossl_ns_spki.c | 20 | ||||
-rw-r--r-- | ossl_pkcs7.c | 138 | ||||
-rw-r--r-- | ossl_pkey.c | 8 | ||||
-rw-r--r-- | ossl_pkey_dsa.c | 155 | ||||
-rw-r--r-- | ossl_pkey_rsa.c | 179 | ||||
-rw-r--r-- | ossl_rand.c | 13 | ||||
-rw-r--r-- | ossl_ssl.c | 102 | ||||
-rw-r--r-- | ossl_version.h | 2 | ||||
-rw-r--r-- | ossl_x509.c | 71 | ||||
-rw-r--r-- | ossl_x509attr.c | 110 | ||||
-rw-r--r-- | ossl_x509crl.c | 57 | ||||
-rw-r--r-- | ossl_x509ext.c | 133 | ||||
-rw-r--r-- | ossl_x509name.c | 215 | ||||
-rw-r--r-- | ossl_x509req.c | 3 | ||||
-rw-r--r-- | ossl_x509revoked.c | 1 | ||||
-rw-r--r-- | ossl_x509store.c | 11 | ||||
-rwxr-xr-x | test/ossl_x509.rb | 9 |
31 files changed, 1622 insertions, 1071 deletions
@@ -4,6 +4,9 @@ Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz> All rights reserved. $Log$ +Revision 1.15 2002/01/04 11:12:45 majkl + * Further checking (Check_SafeStr, memory leaks) + Revision 1.14 2001/12/21 20:10:24 majkl *** empty log message *** @@ -25,6 +25,7 @@ This program is licenced under the same licence as Ruby. = PKCS7 (signing&data_verify is working, rest needs some testing) = HMAC = OpenSSL config file parser (part) += BN (safe bignums) [To-Do] = check for memory leaking :-)) @@ -39,7 +40,6 @@ This program is licenced under the same licence as Ruby. = add aliases to to_pem as s_dump s_load to support Marshal module = CipherFactory? = autogen random IVs for Ciphers -= safe BigNums = PKCS12 = PKCS8 = ASN.1 ??? @@ -57,40 +57,39 @@ This program is licenced under the same licence as Ruby. su root -c make install = Windows like systems: - add to %PATH%: c:\openssl\bin - where the dlls lays + add to %PATH%: c:\openssl\bin (where the dlls lays) ruby extconf.rb --with-openssl-include=c:\openssl\include --with-openssl-lib=c:\openssl\lib nmake nmake install [Documentation/API] - Sorry, not done. See 'test' folder's examples and grep C sources for rb_define_method :-)) + Sorry, not done. See 'test' folder's examples and grep C sources for rb_define_*method :-)) -------------------------------------------------- +=> XXX - XXX is return value +A <=> B - A is an alias to B +[XXX] - argument XXX is optional +A|B - argument can be A or B +bXXX - XXX is true or false +cXXX - XXX is defined as constant +fXXX - XXX is Fixnum +nXXX - XXX is Number (Fixnum or Bignum) +oXXX - argument.kind_of?(XXX) => true +sXXX - XXX is String +tXXX - XXX is instance of Time +-------------------------------------------------- +Integer + .to_bn() => BN.new + OpenSSL:: - .seed(String) => true|false - .load_random_file(Filename) => true|false - .write_random_file(Filename) => true|false + .seed(sSeed) => sSeed + .load_random_file(sFilename) => bResult + .write_random_file(sFilename) => bResult - Config - .new(String (filename)) => self - .get_string(String (section)|nil, String (key)) => String (value) - .get_number(String (section)|nil, String (key)) => String (value) - - HMAC - .new(String(key), Digest) => self - .update(String) => self - .<<(String) <=> .update(String) - .hmac() => String - .hexhmac() => String - .inspect() <=> .hexhmac() - .to_str() <=> .hexhmac() - - Random - .seed(String) => true|false - .load_random_file(String (filename)) => true|false - .write_random_file(String (filename)) => true|false - .random_bytes(size) => String + BN - Doc TODO! + BNError + Cipher:: constants: UNSPEC modes: ECB, CFB, OFB, CBC @@ -103,15 +102,25 @@ OpenSSL:: RC2 (ECB, CBC, BIT40:CBC, BIT64:CBC, CFB, OFB) RC4 (nil, UNSPEC, BIT40) RC5 (ECB, CFB, OFB, CBC) - .new([mode|type] [,type|mode]) => self - .encrypt(Password [, Init_Vect]) => self - .decrypt(Password [, Init_Vect]) => self - .update(String) => String - .<<(String) <=> .update - .cipher => String + .new([cMode|cType] [,cType|cMode]) + .encrypt(sPassword [, sInitVector]) => self + .decrypt(sPassword [, sInitVector]) => self + .update(sData) => s(En|De)crypted + .<< <=> .update + .cipher() => s(En|De)cryptedFinal + + CipherError + + Config + .new(sFilename) + .get_string(sSection|nil, sKey) => sValue + .get_number(sSection|nil, sKey) => nValue + + ConfigError Digest:: MD2 + MD4 MD5 MDC2 RIPEMD160 @@ -119,88 +128,175 @@ OpenSSL:: SHA1 DSS DSS1 - .new([String]) => self - .update(String) => self - .<<(String) <=> .update - .digest => String - .hexdigest => String + .new([sData]) + .update(sData) => self + .<< <=> .update + .digest() => sDigestFinal + .hexdigest() => sHEXDigestFinal .inspect <=> .hexdigest .to_str <=> .hexdigest + + DigestError + + HMAC + .new(sKey, oDigest::ANY) => self + .update(sData) => self + .<< <=> .update + .hmac() => sHMACFinal + .hexhmac() => sHEXHMACFinal + .inspect <=> .hexhmac + .to_str <=> .hexhmac + + HMACError Netscape:: SPKI - .new([String (PEM)]) => self - .to_pem => String (PEM) - .to_str => String - .public_key => PKey - .public_key=(PKey) => PKey - .sign(PKey, Digest) => self - .verify(PKey) => true|false - .challenge => String - .challenge=(String) => String + .new([sPEM]) + .to_pem() => sPEM + .to_str() => sHumanReadable + .public_key() => oPKey::ANY + .public_key=(oPKey::ANY) => oPKey::ANY + .sign(oPKey::ANY, oDigest::ANY) => self + .verify(oPKey::ANY) => bResult + .challenge() => sChallenge + .challenge=(sChallenge) => sChallenge + + SPKIError PKCS7:: - constants: SIGNED, ENVELOPED, SIGNED_ENVELOPED + constants: + type: SIGNED, ENVELOPED, SIGNED_ENVELOPED PKCS7 - .new(CONST|String (PEM)) => self - .add_signer(PKCS7::Signer, PKey (his private)) - .signers => Ary of PKCS7::Signer - .cipher=(Cipher::Any) => Cipher - .add_recipient(X509::Certificate) => self - .add_certificate(X509::Certificate) => self - .add_crl(X509::CRL) => self - .add_data(String (data), [(true|false) (detached?)]) => self - .verify_data(X509::Store, [String (detached)]) => true|false, yields PKCS7::Signer - .decode_data(PKey::Any (private), X509::Certificate) => String - .to_pem => String (PEM) + .new(cType|sPEM) + .cipher=(oCipher::ANY) => oCipher::ANY + .add_signer(oPKCS7::Signer, oPKey::ANY) => self + .signers() => Array of PKCS7::Signer + .add_recipient(oX509::Certificate) => self + .add_certificate(oX509::Certificate) => self + .add_crl(oX509::CRL) => self + .add_data(sData [, bDetached]) => self + .verify_data(oX509::Store [, sDetachedData]) => bResult, yields PKCS7::Signer + .decode_data(oPKey::ANY, oX509::Certificate) => sData + .to_pem() => sPEM Signer - .new(X509::Certificate, PKey (his private), Digest::Any) => self - .name => X509::Name - .serial => FixNum - .signed_time => Time + .new(oX509::Certificate, oPKey::ANY, oDigest::ANY) + .name() => X509::Name + .serial() => fSerial + .signed_time() => tTime + + PKCS7Error + PKey:: + PKeyError + DSA - .new([keylen | String (PEM)]) => self, yields |p,n| when generating new - .public? => true|false - .private? => true|false - .to_str => String - .export([Cipher [, Password]]) => String (PEM) + .new([fKeyLen|sPEM [, sPassword]]) - dispatches .new_from_pem or .generate + .new_from_pem(sPEM [, sPassword]) + .generate(fKeyLen) - yields |p,n| + .new_from_fixnum <=> generate + .public?() => bResult + .private?() => bResult + .to_str() => sHumanReadable + .export([oCipher::ANY [, sPassword]]) => sPEM .to_pem <=> .export - .public_key => pub.key from key - .to_der => String (DER) - .sign(Digest, String) => String - .sign_digest(String (dig)) => String - .verify(Digest, String (data), String (sig)) => true|false - .verify_digest(String (dig), String (sig)) => true|false + .public_key() => oPKey::ANY + .to_der() => sDER + .sign(oDigest::ANY, sData) => sSig + .sign_digest(sDigest) => sSig + .verify(oDigest::ANY, sData, sSig) => bResult + .verify_digest(sDigest, sSig) => bResult + + DSAError RSA - .new([keylen | String (PEM)]) => self, yields |p,n| when generating new - .public? => true|false - .private? => true|false - .to_str => String - .export([Cipher [, Password]]) => String (PEM) + .new([fKeyLen|sPEM [, sPassword]]) - dispatches .new_from_pem or .generate + .new_from_pem(sPEM [, sPassword]) + .generate(fKeyLen) - yields |p,n| + .new_from_fixnum <=> generate + .public?() => bResult + .private?() => bResult + .to_str() => sHumanReadable + .export([oCipher::ANY [, sPassword]]) => sPEM .to_pem <=> .export - .public_key => pub.key from key - .public_encrypt(String) => String - .public_decrypr(String) => String - .private_ecrypt(String) => String - .private_decrypt(String) => String - .to_der => String (DER) - .sign(Digest, String) => String - .verify(Digest, String (data), String (sig)) => true|false + .public_key() => oPKey::ANY + .public_encrypt(sData) => sEnc + .public_decrypt(sEnrypted) => sData + .private_encrypt(sData) => sEnc + .private_decrypt(sEncrypted) => sData + .to_der() => sDER + .sign(oDigest::ANY, sData) => sSig + .verify(oDigest::ANY, sData, sSig) => bResult + + RSAError + Random + .seed(sSeed) => sSeed + .load_random_file(sFilename) => bResult + .write_random_file(sFilename) => bResult + .random_bytes(fLen) => sRandom + + RandomError + + SSL:: - Doc TODO! + + Error + X509:: Attribute - Certificate - CRL - Extension - ExtensionFactory - Name - Request - Revoked - Store + .new(arg) - dispatches "new_from_#{arg.type.name.downcase}" + .new_from_string("oid = value") + .new_from_array(["oid", "value"]) + .new_from_hash({"oid"=>"oid", "value"=>"val"}) + + AttributeError + + Certificate - Doc TODO! + + CertificateError + + CRL - Doc TODO! + + CRLError + + Extension - Doc TODO! + .new is DISABLED! + .to_str => string as "oid = critical, value" + .to_a => ary as ["oid", "value", critical], critical as bool + .to_h => hash as {"oid"=>"oid", "value"=>"val", "critical"=>bool} + + ExtensionFactory - Doc TODO! + .new(...) + .create_extension(*arg) + .create_ext_from_string(str) + .create_ext_from_ary(ary) => X509::Extension, ary as ["oid", "value", critical], critical as bool + .create_ext_from_hash(hash) + + ExtensionError + + Name - Doc TODO! + .new(arg) dispatches "new_from_#{arg.type.name.downcase}" + .new_from_string(str) => self, str as "/A=B/C=D/E=F" + .new_from_array(ary) => self, ary as [["A","B"],["C","D"],["E","F"]] + .new_from_hash(hash) => self, hash as {"A"=>"B","C"=>"D","E"=>"F"} + .to_str => str as "/A=B/C=D/E=F" + .to_a => ary as [["A","B"],["C","D"],["E","F"]] + .to_h => hash as {"A"=>"B","C"=>"D","E"=>"F"} + + NameError + + Request - Doc TODO! + + RequestError + + Revoked - Doc TODO! + + RevokedError + + Store - Doc TODO! + + StoreError -------------------------------------------------- [Examples] @@ -23,6 +23,11 @@ dir_config("openssl") have_func("strncasecmp", "string.h") have_func("strptime", "time.h") +if with_config("debug") or enable_config("debug") # '--enable-debug' or '--with-debug=yes' + $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG" + $CPPFLAGS += " " + "-Wall" unless $CPPFLAGS.split.include? "-Wall" +end + if have_header("openssl/ssl.h") if have_library(CRYPTOLIB, nil) and have_library(SSLLIB, nil) #"SSLv23_method") create_makefile("openssl") diff --git a/lib/openssl.rb b/lib/openssl.rb index aaafed1..7318bf5 100644 --- a/lib/openssl.rb +++ b/lib/openssl.rb @@ -7,6 +7,20 @@ require 'thread' module OpenSSL module PKey class DSA + def DSA.new(arg, pass=nil) + if arg.kind_of? Fixnum + DSA.generate(arg) {|p,n| + if block_given? then yield [p,n] end + } + else + DSA.new_from_pem(arg, pass) + end + end # DSA.new + # + # new_from_pem(PEM string, pass) is built-in + # new_from_fixnum(size) is an alias to generate(size) + # generate(size) is built-in; yields p,n + # def sign(digest, data) unless self.private? raise OpenSSL::PKey::DSAError, "Cannot sign with public key!" @@ -14,39 +28,35 @@ module OpenSSL unless digest.kind_of? OpenSSL::Digest::ANY raise TypeError, "digest alg needed! (got #{digest.class.name})" end - txt = "" - if data.kind_of? String - txt = data - else - begin - txt = data.to_s - rescue - raise TypeError, "string needed! (got #{data.class.name})" - end - end - self.sign_digest digest.update(txt).digest - end #sign + self.sign_digest digest.update(data.to_s).digest + end # sign + def verify(digest, signature, data) unless digest.kind_of? OpenSSL::Digest::ANY raise TypeError, "digest alg needed! (got #{digest.class.name})" end - txt = "" - if data.kind_of? String - txt = data - else - begin - txt = data.to_s - rescue - raise TypeError, "string needed! (got #{data.class.name})" - end - end unless signature.type == String raise TypeError, "Signature as String expected (got #{sign.class.name})" end - self.verify_digest(digest.update(txt).digest, signature) - end #verify - end #DSA + self.verify_digest(digest.update(data.to_s).digest, signature) + end # verify + end # DSA + class RSA + def RSA.new(arg, pass=nil) + if arg.kind_of? Fixnum + RSA.generate(arg) {|p,n| + if block_given? then yield [p,n] end + } + else + RSA.new_from_pem(arg, pass) + end + end # RSA.new + # + # new_from_pem(PEM string, pass) is built-in + # new_from_fixnum(size) is an alias to generate(size) + # generate(size) is built-in; yields p,n + # def sign(digest, data) unless self.private? raise OpenSSL::PKey::RSAError, "Cannot sign with public key!" @@ -54,53 +64,191 @@ module OpenSSL unless digest.kind_of? OpenSSL::Digest::ANY raise TypeError, "digest alg needed! (got #{digest.class.name})" end - txt = "" - if data.kind_of? String - txt = data - else - begin - txt = data.to_s - rescue - raise TypeError, "string needed! (got #{data.class.name})" - end - end - self.private_encrypt digest.update(txt).digest - end #sign + self.private_encrypt digest.update(data.to_s).digest + end # sign + def verify(digest, signature, data) unless digest.kind_of? OpenSSL::Digest::ANY raise TypeError, "digest alg needed! (got #{digest.class.name})" end - txt = "" - if data.kind_of? String - txt = data - else - begin - txt = data.to_s - rescue - raise TypeError, "string needed! (got #{data.class.name})" - end - end unless signature.type == String raise TypeError, "Signature as String expected (got #{sign.class.name})" end - hash_s = self.public_decrypt signature - hash_d = digest.update(txt).digest - hash_s == hash_d - end #verify - end #RSA - end #PKey + md_s = self.public_decrypt signature + md_d = digest.update(data.to_s).digest + md_s == md_d + end # verify + end # RSA + end # PKey module SSL class SSLSocket - CallbackMutex = Mutex.new include Buffering + CallbackMutex = Mutex.new + def connect CallbackMutex.synchronize{ __connect } end + def accept CallbackMutex.synchronize{ __accept } end - end #SSLSocket - end #SSL -end #OpenSSL + end # SSLSocket + end # SSL + + module X509 + class Name + def Name.new(arg) + Name.send("new_from_#{arg.type.name.downcase}", arg) + end + # + # Name.new_from_hash(hash) is built-in method + # + def Name.new_from_string(str) # we're expecting string like "/A=B/C=D/E=F" + hash = {} + ary = [] # speed optim. + str.split("/")[1..-1].each do |item| # first item is "" - so skip it + ary = item.split("=") + hash[ary[0]] = ary[1] + end + Name.new_from_hash(hash) + end + + def Name.new_from_array(ary) # [["A","B"],["C","D"],["E","F"]] + hash = {} + ary.each do |item| + hash[item[0]] = item[1] + end + Name.new_from_hash(hash) + end + # + # to_h is built-in method + # + def to_str # "/A=B/C=D/E=F" + hash = self.to_h + str = "" + hash.keys.each do |key| + str += "/" + key + "=" + hash[key] + end + str + end + + def to_a # [["A","B"],["C","D"],["E","F"]] + self.to_h.to_a + end + end # Name + + class ExtensionFactory + def create_extension(*arg) + if arg.size == 1 then arg = arg[0] end + send("create_ext_from_#{arg.type.name.downcase}", arg) + end + # + # create_ext_from_array is built-in + # + def create_ext_from_string(str) # "oid = critical, value" + unless str =~ /\s*=\s*/ + raise ArgumentError, "string in format \"oid = value\" expected" + end + ary = [] + ary << $`.sub(/^\s*/,"") # delete whitespaces from the beginning + rest = $'.sub(/\s*$/,"") # delete them from the end + if rest =~ /^critical,\s*/ # handle 'critical' option + ary << $' + ary << true + else + ary << rest + end + create_ext_from_array(ary) + end + + def create_ext_from_hash(hash) # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} + unless (hash.has_key? "oid" and hash.has_key? "value") + raise ArgumentError, "hash in format {\"oid\"=>..., \"value\"=>...} expected" + end + ary = [] + ary << hash["oid"] + ary << hash["value"] + ary << hash["critical"] if hash.has_key? "critical" + create_ext_from_array(ary) + end + end # ExtensionFactory + + class Extension + # note: Extension.new is UNDEFed! - use ExtensionFactory.create_extension + # + # to_a is built-in + # + def to_str # "oid = critical, value" + ary = self.to_a + str = ary[0] + " = " + str += "critical, " if ary[2] == true + str += ary[1] + end + + def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} + ary = self.to_a + {"oid"=>ary[0],"value"=>ary[1],"critical"=>ary[2]} + end + + def oid + self.to_a[0] + end + + def value + self.to_a[1] + end + + def critical? + self.to_a[2] + end + end # Extension + + class Attribute + def Attribute.new(arg) + Attribute.send("new_from_#{arg.type.name.downcase}", arg) + end + # + # Attribute.new_from_array(ary) is built-in method + # + def Attribute.new_from_string(str) # "oid = value" + unless str =~ /\s*=\s*/ + raise ArgumentError, "string in format \"oid = value\" expected" + end + ary = [] + ary << $`.sub(/^\s*/,"") # delete whitespaces from the beginning + ary << $'.sub(/\s*$/,"") # delete them from the end + Attribute.new_from_array(ary) + end + + def Attribute.new_from_hash(hash) # {"oid"=>"...", "value"=>"..."} + unless (hash.has_key? "oid" and hash.has_key? "value") + raise ArgumentError, "hash in format {\"oid\"=>..., \"value\"=>...} expected" + end + ary = [] + ary << hash["oid"] + ary << hash["value"] + Attribute.new_from_array(ary) + end + end # Attribute + end # X509 + + class BN + def BN.new(arg) + BN.new_from_dec(arg.to_s) + end + + alias :to_str :to_dec + + def to_i + self.to_str.to_i + end + end # BN +end # OpenSSL + +class Integer + def to_bn + OpenSSL::BN.new(self) + end +end # Integer diff --git a/missing/strncasecmp.c b/missing/strncasecmp.c new file mode 100644 index 0000000..e4d1bb9 --- /dev/null +++ b/missing/strncasecmp.c @@ -0,0 +1,19 @@ +#include <ctype.h> + +int +strncasecmp(p1, p2, len) + char *p1; + char *p2; + int len; +{ + for (; len != 0; len--, p1++, p2++) { + if (toupper(*p1) != toupper(*p2)) { + return toupper(*p1) - toupper(*p2); + } + if (*p1 == '\0') { + return 0; + } + } + return 0; +} + diff --git a/missing/strptime.c b/missing/strptime.c new file mode 100644 index 0000000..15d9268 --- /dev/null +++ b/missing/strptime.c @@ -0,0 +1,363 @@ +/* + * Copyright (c) 1994 Powerdog Industries. All rights reserved. + * + * Redistribution and use in source and binary forms, without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgement: + * This product includes software developed by Powerdog Industries. + * 4. The name of Powerdog Industries may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <stdio.h> +#include <stdlib.h> +/* #include <unistd.h> */ +#include <time.h> +#include <ctype.h> +#include <string.h> + +#ifndef HAVE_STRNCASECMP +# include "./strncasecmp.c" +#endif + +/* +#if !defined(WIN32) +# include "common/config.h" +#endif +*/ + +#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) + +#ifndef sun +struct dtconv { + char *abbrev_month_names[12]; + char *month_names[12]; + char *abbrev_weekday_names[7]; + char *weekday_names[7]; + char *time_format; + char *sdate_format; + char *dtime_format; + char *am_string; + char *pm_string; + char *ldate_format; +}; +#endif + +static struct dtconv En_US = { + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }, + { "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December" }, + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }, + { "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" }, + "%H:%M:%S", + "%m/%d/%y", + "%a %b %e %T %Z %Y", + "AM", + "PM", + "%A, %B, %e, %Y" +}; + +#ifdef SUNOS4 +extern int strncasecmp(); +#endif + +char * +strptime(char *buf, char *fmt, struct tm *tm) +{ + char c, + *ptr; + int i, + len; + + ptr = fmt; + while (*ptr != 0) { + if (*buf == 0) + break; + + c = *ptr++; + + if (c != '%') { + if (isspace(c)) + while (*buf != 0 && isspace(*buf)) + buf++; + else if (c != *buf++) + return 0; + continue; + } + + c = *ptr++; + switch (c) { + case 0: + case '%': + if (*buf++ != '%') + return 0; + break; + + case 'C': + buf = strptime(buf, En_US.ldate_format, tm); + if (buf == 0) + return 0; + break; + + case 'c': + buf = strptime(buf, "%x %X", tm); + if (buf == 0) + return 0; + break; + + case 'D': + buf = strptime(buf, "%m/%d/%y", tm); + if (buf == 0) + return 0; + break; + + case 'R': + buf = strptime(buf, "%H:%M", tm); + if (buf == 0) + return 0; + break; + + case 'r': + buf = strptime(buf, "%I:%M:%S %p", tm); + if (buf == 0) + return 0; + break; + + case 'T': + buf = strptime(buf, "%H:%M:%S", tm); + if (buf == 0) + return 0; + break; + + case 'X': + buf = strptime(buf, En_US.time_format, tm); + if (buf == 0) + return 0; + break; + + case 'x': + buf = strptime(buf, En_US.sdate_format, tm); + if (buf == 0) + return 0; + break; + + case 'j': + if (!isdigit(*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i > 365) + return 0; + + tm->tm_yday = i; + break; + + case 'M': + case 'S': + if (*buf == 0 || isspace(*buf)) + break; + + if (!isdigit(*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i > 59) + return 0; + + if (c == 'M') + tm->tm_min = i; + else + tm->tm_sec = i; + + if (*buf != 0 && isspace(*buf)) + while (*ptr != 0 && !isspace(*ptr)) + ptr++; + break; + + case 'H': + case 'I': + case 'k': + case 'l': + if (!isdigit(*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (c == 'H' || c == 'k') { + if (i > 23) + return 0; + } else if (i > 11) + return 0; + + tm->tm_hour = i; + + if (*buf != 0 && isspace(*buf)) + while (*ptr != 0 && !isspace(*ptr)) + ptr++; + break; + + case 'p': + len = strlen(En_US.am_string); + if (strncasecmp(buf, En_US.am_string, len) == 0) { + if (tm->tm_hour > 12) + return 0; + if (tm->tm_hour == 12) + tm->tm_hour = 0; + buf += len; + break; + } + + len = strlen(En_US.pm_string); + if (strncasecmp(buf, En_US.pm_string, len) == 0) { + if (tm->tm_hour > 12) + return 0; + if (tm->tm_hour != 12) + tm->tm_hour += 12; + buf += len; + break; + } + + return 0; + + case 'A': + case 'a': + for (i = 0; i < asizeof(En_US.weekday_names); i++) { + len = strlen(En_US.weekday_names[i]); + if (strncasecmp(buf, + En_US.weekday_names[i], + len) == 0) + break; + + len = strlen(En_US.abbrev_weekday_names[i]); + if (strncasecmp(buf, + En_US.abbrev_weekday_names[i], + len) == 0) + break; + } + if (i == asizeof(En_US.weekday_names)) + return 0; + + tm->tm_wday = i; + buf += len; + break; + + case 'd': + case 'e': + if (!isdigit(*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i > 31) + return 0; + + tm->tm_mday = i; + + if (*buf != 0 && isspace(*buf)) + while (*ptr != 0 && !isspace(*ptr)) + ptr++; + break; + + case 'B': + case 'b': + case 'h': + for (i = 0; i < asizeof(En_US.month_names); i++) { + len = strlen(En_US.month_names[i]); + if (strncasecmp(buf, + En_US.month_names[i], + len) == 0) + break; + + len = strlen(En_US.abbrev_month_names[i]); + if (strncasecmp(buf, + En_US.abbrev_month_names[i], + len) == 0) + break; + } + if (i == asizeof(En_US.month_names)) + return 0; + + tm->tm_mon = i; + buf += len; + break; + + case 'm': + if (!isdigit(*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i < 1 || i > 12) + return 0; + + tm->tm_mon = i - 1; + + if (*buf != 0 && isspace(*buf)) + while (*ptr != 0 && !isspace(*ptr)) + ptr++; + break; + + case 'Y': + case 'y': + if (*buf == 0 || isspace(*buf)) + break; + + if (!isdigit(*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (c == 'Y') + i -= 1900; + if (i < 0) + return 0; + + tm->tm_year = i; + + if (*buf != 0 && isspace(*buf)) + while (*ptr != 0 && !isspace(*ptr)) + ptr++; + break; + } + } + + return buf; +} + diff --git a/openssl_missing.c b/openssl_missing.c index 41ff5fe..3fe4027 100644 --- a/openssl_missing.c +++ b/openssl_missing.c @@ -11,7 +11,6 @@ #ifndef NO_HMAC #include <openssl/hmac.h> -#include "openssl_missing.h" /* to hmac.[ch] */ int @@ -8,10 +8,18 @@ * This program is licenced under the same licence as Ruby. * (See the file 'LICENCE'.) */ -#include <openssl/err.h> +/*#include <openssl/err.h>*/ #include "ossl.h" /* + * On Windows platform there is no strptime function + * implementation in strptime.c + */ +#ifndef HAVE_STRPTIME +# include "./missing/strptime.c" +#endif + +/* * Check Types */ void ossl_check_type(VALUE obj, VALUE klass) @@ -22,22 +30,6 @@ void ossl_check_type(VALUE obj, VALUE klass) } } -/* - * Error messages - */ -char *ossl_error(void) -{ - return ERR_error_string(ERR_get_error(), NULL); -} - -/* - * On Windows platform there is no strptime function - * implementation in strptime.c - */ -#ifndef HAVE_STRPTIME -char *strptime(char *buf, char *fmt, struct tm *tm); -#endif - VALUE asn1time_to_time(ASN1_UTCTIME *time) { struct tm tm; @@ -56,7 +48,7 @@ VALUE asn1time_to_time(ASN1_UTCTIME *time) default: rb_raise(rb_eTypeError, "unknown time format"); } - /*return rb_time_new(mktime(gmtime(mktime(&tm))), 0); /* Is this correct? */ + /*return rb_time_new(mktime(gmtime(mktime(&tm))), 0); * Is this correct? */ return rb_time_new(mktime(&tm), 0); /* or this one? */ } @@ -122,3 +114,10 @@ Init_openssl() Init_bn(mOSSL); } +#if defined(OSSL_DEBUG) +int main(int argc, char *argv[], char *env[]) +{ + return 0; +} +#endif /* OSSL_DEBUG */ + @@ -11,10 +11,15 @@ #ifndef _OSSL_H_ #define _OSSL_H_ +#ifdef __cplusplus +extern "C" { +#endif + #if defined(NT) # define OpenFile WINAPI_OpenFile #endif #include <errno.h> +#include <openssl/err.h> #include <openssl/asn1_mac.h> #include <openssl/x509v3.h> #include <openssl/ssl.h> @@ -24,17 +29,13 @@ # undef OpenFile #endif -#ifdef __cplusplus -extern "C" { -#endif - #include "openssl_missing.h" #include "ossl_version.h" /* * OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it! */ -#if !defined(OSSL_DEBUG) && defined(RFILE) +#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/ # undef RFILE #endif #include <ruby.h> @@ -77,6 +78,7 @@ extern VALUE cRandom; extern VALUE eRandomError; extern VALUE cSSLSocket; extern VALUE eSSLError; + /* Cipher */ extern VALUE cCipher; extern VALUE eCipherError; @@ -91,7 +93,7 @@ extern VALUE ePKeyError; extern VALUE cRSA; extern VALUE eRSAError; extern VALUE cDSA; -extern VALUE cDSAError; +extern VALUE eDSAError; /* PKCS7 */ extern VALUE cPKCS7; extern VALUE cPKCS7SignerInfo; @@ -120,7 +122,28 @@ VALUE asn1time_to_time(ASN1_UTCTIME *); /* * ERRor messages */ -char *ossl_error(void); +#define ossl_error OSSL_ErrMsg /* for compat.; DEPRECATED! */ +#define OSSL_ErrMsg() \ + ERR_error_string(ERR_get_error(), NULL) + +#if defined(OSSL_DEBUG) +# define OSSL_Raise(klass,text) \ + rb_raise(klass, "%s%s [in '%s', file: '%s', line: %d]", \ + text, OSSL_ErrMsg(), __func__, __FILE__, __LINE__) +# define OSSL_Warn(text) \ + rb_warn("%s%s [in '%s', file: '%s', line: %d]", \ + text, OSSL_ErrMsg(), __func__, __FILE__, __LINE__) +# define OSSL_Warning(text) \ + rb_warning("%s%s [in '%s', file: '%s', line: %d]", \ + text, OSSL_ErrMsg(), __func__, __FILE__, __LINE__) +#else +# define OSSL_Raise(klass,text) \ + rb_raise(klass, "%s%s", text, OSSL_ErrMsg()) +# define OSSL_Warn(text) \ + rb_warn("%s%s", text, OSSL_ErrMsg()) +# define OSSL_Warning(text) \ + rb_warning("%s%s", text, OSSL_ErrMsg()) +#endif /*OSSL_DEBUG*/ /* * Config @@ -229,7 +252,7 @@ VALUE ossl_rsa_new_null(); VALUE ossl_rsa_new(RSA *); RSA *ossl_rsa_get_RSA(VALUE); EVP_PKEY *ossl_rsa_get_EVP_PKEY(VALUE); -#endif +#endif /*NO_RSA*/ void Init_ossl_rsa(VALUE, VALUE, VALUE); /* @@ -240,7 +263,7 @@ VALUE ossl_dsa_new_null(); VALUE ossl_dsa_new(DSA *); DSA *ossl_dsa_get_DSA(VALUE); EVP_PKEY *ossl_dsa_get_EVP_PKEY(VALUE); -#endif +#endif /*NO_RSA*/ void Init_ossl_dsa(VALUE, VALUE, VALUE); /* @@ -273,5 +296,5 @@ void Init_bn(VALUE); } #endif -#endif +#endif /*_OSSL_H_*/ @@ -15,9 +15,8 @@ obj = Data_Make_Struct(cBN, ossl_bn, 0, ossl_bn_free, bnp);\ } -#define GetBN_unsafe(obj, bnp) Data_Get_Struct(obj, ossl_bn, bnp) #define GetBN(obj, bnp) {\ - GetBN_unsafe(obj, bnp);\ + Data_Get_Struct(obj, ossl_bn, bnp);\ if (!bnp->bignum) rb_raise(eBNError, "not initialized!");\ } @@ -55,9 +54,9 @@ ossl_bn_new_null(void) MakeBN(obj, bnp); - if (!(bnp->bignum = BN_new())) { - rb_raise(eBNError, "%s", ossl_error()); - } + if (!(bnp->bignum = BN_new())) + OSSL_Raise(eBNError, ""); + return obj; } @@ -72,9 +71,8 @@ ossl_bn_new(BIGNUM *bn) MakeBN(obj, bnp); - if (!(bnp->bignum = BN_dup(bn))) { - rb_raise(eBNError, "%s", ossl_error()); - } + if (!(bnp->bignum = BN_dup(bn))) + OSSL_Raise(eBNError, ""); return obj; } @@ -88,9 +86,8 @@ ossl_bn_get_BIGNUM(VALUE obj) OSSL_Check_Type(obj, cBN); GetBN(obj, bnp); - if (!(bn = BN_dup(bnp->bignum))) { - rb_raise(eBNError, "%s", ossl_error()); - } + if (!(bn = BN_dup(bnp->bignum))) + OSSL_Raise(eBNError, ""); return bn; } @@ -105,91 +102,124 @@ ossl_bn_new_nodup(BIGNUM *bn) VALUE obj; MakeBN(obj, bnp); - bnp->bignum = bn; return obj; } -static VALUE -ossl_bn_s_new(int argc, VALUE *argv, VALUE klass) -{ - ossl_bn *bnp = NULL; - VALUE obj; - - MakeBN(obj, bnp); +#define BIGNUM_NEW(func) \ + static VALUE \ + ossl_bn_s_new_from_##func(VALUE klass, VALUE str) \ + { \ + ossl_bn *bnp = NULL; \ + BIGNUM *bn = NULL; \ + VALUE obj; \ + \ + Check_SafeStr(str); \ + \ + if (!(bn = BN_new())) \ + OSSL_Raise(eBNError, ""); \ + \ + if (!BN_##func##2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) \ + OSSL_Raise(eBNError, ""); \ + \ + MakeBN(obj, bnp); \ + bnp->bignum = bn; \ + \ + return obj; \ + } +BIGNUM_NEW(bin); +BIGNUM_NEW(mpi); - rb_obj_call_init(obj, argc, argv); - return obj; -} +#define BIGNUM_NEW2(func) \ + static VALUE \ + ossl_bn_s_new_from_##func(VALUE klass, VALUE str) \ + { \ + ossl_bn *bnp = NULL; \ + BIGNUM *bn = NULL; \ + VALUE obj; \ + \ + Check_SafeStr(str); \ + \ + if (!(bn = BN_new())) \ + OSSL_Raise(eBNError, ""); \ + \ + if (!BN_##func##2bn(&bn, RSTRING(str)->ptr)) \ + OSSL_Raise(eBNError, ""); \ + \ + MakeBN(obj, bnp); \ + bnp->bignum = bn; \ + \ + return obj; \ + } +BIGNUM_NEW2(dec); +BIGNUM_NEW2(hex); static VALUE -ossl_bn_initialize(int argc, VALUE *argv, VALUE self) +ossl_bn_to_bin(VALUE self) { ossl_bn *bnp = NULL; - BIGNUM *bn = NULL; - VALUE number, str; - - GetBN_unsafe(self, bnp); + char *buf = NULL; + int len; + VALUE str; - rb_scan_args(argc, argv, "10", &number); - - /* - * nothing given - create empty one - */ - if (NIL_P(number)) { - if (!(bn = BN_new())) { - rb_raise(eBNError, "%s", ossl_error()); - } - bnp->bignum = bn; - - return self; - } + GetBN(self, bnp); - /* - * else - convert it to str and use BN_dec2bn - */ - switch (TYPE(number)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - str = rb_funcall(number, rb_intern("to_s"), 0, NULL); - break; - case T_STRING: - Check_SafeStr(number); - str = number; - break; - default: - rb_raise(rb_eTypeError, "unsupported argument (%s)", rb_class2name(CLASS_OF(number))); - } + len = BN_num_bytes(bnp->bignum); + buf = OPENSSL_malloc(len); - if (!BN_dec2bn(&bn, RSTRING(str)->ptr)) { - rb_raise(eBNError, "%s", ossl_error()); - } - bnp->bignum = bn; - - return self; + if (BN_bn2bin(bnp->bignum, buf) != len) + OSSL_Raise(eBNError, ""); + + str = rb_str_new(buf, len); + OPENSSL_free(buf); + + return str; } static VALUE -ossl_bn_to_i(VALUE self) +ossl_bn_to_mpi(VALUE self) { ossl_bn *bnp = NULL; - char *str = NULL; - VALUE num; + char *buf = NULL; + int len; + VALUE str; GetBN(self, bnp); - - if (!(str = BN_bn2dec(bnp->bignum))) { - rb_raise(eBNError, "%s", ossl_error()); - } - - num = rb_cstr2inum(str, 10); - OPENSSL_free(str); - return num; + len = BN_bn2mpi(bnp->bignum, NULL); + buf = OPENSSL_malloc(len); + + if (BN_bn2mpi(bnp->bignum, buf) != len) + OSSL_Raise(eBNError, ""); + + str = rb_str_new(buf, len); + OPENSSL_free(buf); + + return str; } +#define BIGNUM_TO_STR(func) \ + static VALUE \ + ossl_bn_to_##func(VALUE self) \ + { \ + ossl_bn *bnp = NULL; \ + char *txt = NULL; \ + VALUE str; \ + \ + GetBN(self, bnp); \ + \ + if (!(txt = BN_bn2##func(bnp->bignum))) \ + OSSL_Raise(eBNError, ""); \ + \ + str = rb_str_new2(txt); \ + OPENSSL_free(txt); \ + \ + return str; \ + } +BIGNUM_TO_STR(dec); +BIGNUM_TO_STR(hex); + #define BIGNUM_BOOL1(func) \ static VALUE \ ossl_bn_##func(VALUE self) \ @@ -218,12 +248,12 @@ BIGNUM_BOOL1(is_odd); GetBN(self, bnp); \ \ if (!(result = BN_new())) \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ \ BN_CTX_init(&ctx); \ if (BN_##func(result, bnp->bignum, &ctx) != 1) { \ BN_free(result); \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ } \ \ return ossl_bn_new_nodup(result); \ @@ -234,8 +264,7 @@ BIGNUM_1c(sqr); static VALUE \ ossl_bn_##func(VALUE self, VALUE other) \ { \ - ossl_bn *bn1p = NULL; \ - ossl_bn *bn2p = NULL; \ + ossl_bn *bn1p = NULL, *bn2p = NULL; \ BIGNUM *result = NULL; \ \ GetBN(self, bn1p); \ @@ -244,11 +273,11 @@ BIGNUM_1c(sqr); GetBN(other, bn2p); \ \ if (!(result = BN_new())) \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ \ if (BN_##func(result, bn1p->bignum, bn2p->bignum) != 1) { \ BN_free(result); \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ } \ \ return ossl_bn_new_nodup(result); \ @@ -270,12 +299,12 @@ BIGNUM_2(sub); GetBN(other, bn2p); \ \ if (!(result = BN_new())) \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ \ BN_CTX_init(&ctx); \ - if (BN_##func(result, bn1p->bignum, bn2p->bignum, &ctx) != 1) { \ + if (BN_##func(result, bn1p->bignum, bn2p->bignum, &ctx) != 1) { \ BN_free(result); \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ } \ \ return ossl_bn_new_nodup(result); \ @@ -299,17 +328,17 @@ ossl_bn_div(VALUE self, VALUE other) GetBN(other, bn2p); if (!(r1 = BN_new())) - rb_raise(eBNError, "%s", ossl_error()); + OSSL_Raise(eBNError, ""); if (!(r2 = BN_new())) { BN_free(r1); - rb_raise(eBNError, "%s", ossl_error()); + OSSL_Raise(eBNError, ""); } BN_CTX_init(&ctx); if (BN_div(r1, r2, bn1p->bignum, bn2p->bignum, &ctx) != 1) { BN_free(r1); BN_free(r2); - rb_raise(eBNError, "%s", ossl_error()); + OSSL_Raise(eBNError, ""); } obj1 = ossl_bn_new_nodup(r1); @@ -331,12 +360,12 @@ ossl_bn_mod_inverse(VALUE self, VALUE other) GetBN(other, bn2p); if (!(result = BN_new())) - rb_raise(eBNError, "%s", ossl_error()); + OSSL_Raise(eBNError, ""); BN_CTX_init(&ctx); if (BN_mod_inverse(result, bn1p->bignum, bn2p->bignum, &ctx) == NULL) { BN_free(result); - rb_raise(eBNError, "%s", ossl_error()); + OSSL_Raise(eBNError, ""); } return ossl_bn_new_nodup(result); @@ -358,12 +387,12 @@ ossl_bn_mod_inverse(VALUE self, VALUE other) GetBN(other2, bn3p); \ \ if (!(result = BN_new())) \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ \ BN_CTX_init(&ctx); \ if (BN_##func(result, bn1p->bignum, bn2p->bignum, bn3p->bignum, &ctx) != 1) { \ BN_free(result); \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ } \ \ return ossl_bn_new_nodup(result); \ @@ -380,7 +409,7 @@ BIGNUM_3c(mod_exp); GetBN(self, bnp); \ \ if (BN_##func(bnp->bignum, NUM2INT(bit)) != 1) \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ \ return self; \ } @@ -408,7 +437,7 @@ ossl_bn_mask_bits(VALUE self, VALUE bit) GetBN(self, bnp); if (BN_mask_bits(bnp->bignum, NUM2INT(bit)) != 1) - rb_raise(eBNError, "%s", ossl_error()); + OSSL_Raise(eBNError, ""); return self; } @@ -423,11 +452,11 @@ ossl_bn_mask_bits(VALUE self, VALUE bit) GetBN(self, bnp); \ \ if (!(result = BN_new())) \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ \ if (BN_##func(result, bnp->bignum, NUM2INT(bits)) != 1) { \ BN_free(result); \ - rb_raise(eBNError, "%s", ossl_error()); \ + OSSL_Raise(eBNError, ""); \ } \ \ return ossl_bn_new_nodup(result); \ @@ -435,18 +464,108 @@ ossl_bn_mask_bits(VALUE self, VALUE bit) BIGNUM_SHIFT(lshift); BIGNUM_SHIFT(rshift); +#define BIGNUM_RAND(func) \ + static VALUE \ + ossl_bn_s_##func(VALUE klass, VALUE bits, VALUE top, VALUE bottom) \ + { \ + BIGNUM *result = NULL; \ + \ + if (!(result = BN_new())) \ + OSSL_Raise(eBNError, ""); \ + \ + if (!BN_##func(result, NUM2INT(bits), NUM2INT(top), NUM2INT(bottom))) \ + OSSL_Raise(eBNError, ""); \ + \ + return ossl_bn_new_nodup(result); \ + } +BIGNUM_RAND(rand); +BIGNUM_RAND(pseudo_rand); + +static VALUE +ossl_bn_s_rand_range(VALUE klass, VALUE range) +{ + ossl_bn *bnp = NULL; + BIGNUM *result = NULL; + + OSSL_Check_Type(range, cBN); + GetBN(range, bnp); + + if (!(result = BN_new())) + OSSL_Raise(eBNError, ""); + + if (!BN_rand_range(result, bnp->bignum)) + OSSL_Raise(eBNError, ""); + + return ossl_bn_new_nodup(result); +} + +#define BIGNUM_RETURN_INT(func) \ + static VALUE \ + ossl_bn_##func(VALUE self) \ + { \ + ossl_bn *bnp = NULL; \ + \ + GetBN(self, bnp); \ + \ + return INT2FIX(BN_##func(bnp->bignum)); \ + } +BIGNUM_RETURN_INT(num_bytes); +BIGNUM_RETURN_INT(num_bits); + +static VALUE +ossl_bn_dup(VALUE self) +{ + ossl_bn *bnp = NULL; + + GetBN(self, bnp); + + return ossl_bn_new(bnp->bignum); +} + +#define BIGNUM_CMP(func) \ + static VALUE \ + ossl_bn_##func(VALUE self, VALUE other) \ + { \ + ossl_bn *bn1p = NULL, *bn2p = NULL; \ + \ + GetBN(self, bn1p); \ + \ + OSSL_Check_Type(other, cBN); \ + GetBN(other, bn2p); \ + \ + return INT2FIX(BN_##func(bn1p->bignum, bn2p->bignum)); \ + } +BIGNUM_CMP(cmp); +BIGNUM_CMP(ucmp); + +static VALUE +ossl_bn_eql(VALUE self, VALUE other) +{ + if (FIX2INT(ossl_bn_cmp(self, other)) == 0) + return Qtrue; + + return Qfalse; +} + /* * INIT */ void -Init_bn(VALUE mOSSL) +Init_bn(VALUE module) { - eBNError = rb_define_class_under(mOSSL, "BNError", ePKeyError); + eBNError = rb_define_class_under(module, "BNError", ePKeyError); - cBN = rb_define_class_under(mOSSL, "BN", cPKey); - rb_define_singleton_method(cBN, "new", ossl_bn_s_new, -1); - rb_define_method(cBN, "initialize", ossl_bn_initialize, -1); - rb_define_method(cBN, "to_i", ossl_bn_to_i, 0); + cBN = rb_define_class_under(module, "BN", cPKey); + + rb_define_singleton_method(cBN, "new_from_bin", ossl_bn_s_new_from_bin, 1); + rb_define_singleton_method(cBN, "new_from_mpi", ossl_bn_s_new_from_mpi, 1); + rb_define_singleton_method(cBN, "new_from_dec", ossl_bn_s_new_from_dec, 1); + rb_define_singleton_method(cBN, "new_from_hex", ossl_bn_s_new_from_hex, 1); + + rb_define_method(cBN, "to_bin", ossl_bn_to_bin, 0); + rb_define_method(cBN, "to_mpi", ossl_bn_to_mpi, 0); + rb_define_method(cBN, "to_dec", ossl_bn_to_dec, 0); + rb_define_method(cBN, "to_hex", ossl_bn_to_hex, 0); rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); rb_define_method(cBN, "one?", ossl_bn_is_one, 0); @@ -476,5 +595,22 @@ Init_bn(VALUE mOSSL) rb_define_method(cBN, "<<", ossl_bn_lshift, 1); rb_define_method(cBN, ">>", ossl_bn_rshift, 1); + + rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, 3); + rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, 3); + rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); + + rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0); + rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0); + + rb_define_method(cBN, "dup", ossl_bn_dup, 0); + + rb_define_method(cBN, "cmp", ossl_bn_cmp, 1); + rb_define_alias(cBN, "<=>", "cmp"); + rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); + + rb_define_method(cBN, "eql?", ossl_bn_eql, 1); + rb_define_alias(cBN, "==", "eql?"); + rb_define_alias(cBN, "===", "eql?"); } diff --git a/ossl_cipher.c b/ossl_cipher.c index 0c28d34..0a2f37e 100644 --- a/ossl_cipher.c +++ b/ossl_cipher.c @@ -72,7 +72,6 @@ ossl_cipher_get_NID(VALUE obj) ossl_cipher *ciphp = NULL; OSSL_Check_Type(obj, cCipher); - GetCipher(obj, ciphp); return ciphp->nid; /*EVP_CIPHER_CTX_nid(ciphp->ctx);*/ @@ -84,7 +83,6 @@ ossl_cipher_get_EVP_CIPHER(VALUE obj) ossl_cipher *ciphp = NULL; OSSL_Check_Type(obj, cCipher); - GetCipher(obj, ciphp); return EVP_get_cipherbynid(ciphp->nid); /*EVP_CIPHER_CTX_cipher(ciphp->ctx);*/ @@ -103,9 +101,9 @@ ossl_cipher_s_new(int argc, VALUE *argv, VALUE klass) rb_raise(rb_eNotImpError, "cannot do Cipher::ANY.new - it is an abstract class"); MakeCipher(obj, klass, ciphp); - if (!(ciphp->ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)))) { - rb_raise(eCipherError, "%s", ossl_error()); - } + + if (!(ciphp->ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)))) + OSSL_Raise(eCipherError, ""); rb_obj_call_init(obj, argc, argv); @@ -135,9 +133,9 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) /* RAND_add(data,i,0); where from take data? if (RAND_pseudo_bytes(iv, 8) < 0) { - rb_raise(eCipherError, "%s", ossl_error()); + OSSL_Raise(eCipherError, ""); } - */ + */ } else { Check_SafeStr(init_v); memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv)); @@ -147,9 +145,8 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) cipher = EVP_get_cipherbynid(ciphp->nid); EVP_BytesToKey(cipher, EVP_md5(), iv, RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); - if (!EVP_EncryptInit(ciphp->ctx, cipher, key, iv)) { - rb_raise(eCipherError, "%s", ossl_error()); - } + if (!EVP_EncryptInit(ciphp->ctx, cipher, key, iv)) + OSSL_Raise(eCipherError, ""); return self; } @@ -167,6 +164,7 @@ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "11", &pass, &init_v); Check_SafeStr(pass); + if (NIL_P(init_v)) { /* * TODO: @@ -181,13 +179,12 @@ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) cipher = EVP_get_cipherbynid(ciphp->nid); - /*if (!load_iv((unsigned char **)&header,&(cipher->iv[0]),8)) return(0); /* cipher = CIPHER_INFO */ + /*if (!load_iv((unsigned char **)&header,&(cipher->iv[0]),8)) return(0); * cipher = CIPHER_INFO */ EVP_BytesToKey(cipher, EVP_md5(), iv, RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); - if (!EVP_DecryptInit(ciphp->ctx, cipher, key, iv)) { - rb_raise(eCipherError, "%s", ossl_error()); - } + if (!EVP_DecryptInit(ciphp->ctx, cipher, key, iv)) + OSSL_Raise(eCipherError, ""); return self; } @@ -206,12 +203,12 @@ ossl_cipher_update(VALUE self, VALUE data) in = RSTRING(data)->ptr; in_len = RSTRING(data)->len; - if (!(out = OPENSSL_malloc(in_len + EVP_CIPHER_CTX_block_size(ciphp->ctx)))) { - rb_raise(eCipherError, "%s", ossl_error()); - } + if (!(out = OPENSSL_malloc(in_len + EVP_CIPHER_CTX_block_size(ciphp->ctx)))) + OSSL_Raise(eCipherError, ""); + if (!EVP_CipherUpdate(ciphp->ctx, out, &out_len, in, in_len)) { OPENSSL_free(out); - rb_raise(eCipherError, "%s", ossl_error()); + OSSL_Raise(eCipherError, ""); } str = rb_str_new(out, out_len); @@ -231,12 +228,12 @@ ossl_cipher_cipher(VALUE self) GetCipher(self, ciphp); - if (!(out = OPENSSL_malloc(EVP_CIPHER_CTX_block_size(ciphp->ctx)))) { - rb_raise(eCipherError, "%s", ossl_error()); - } + if (!(out = OPENSSL_malloc(EVP_CIPHER_CTX_block_size(ciphp->ctx)))) + OSSL_Raise(eCipherError, ""); + if (!EVP_CipherFinal(ciphp->ctx, out, &out_len)) { OPENSSL_free(out); - rb_raise(eCipherError, "%s", ossl_error()); + OSSL_Raise(eCipherError, ""); } str = rb_str_new(out, out_len); OPENSSL_free(out); @@ -300,7 +297,6 @@ ossl_des_initialize(int argc, VALUE *argv, VALUE self) break; default: rb_raise(rb_eTypeError, "unsupported combination of modes"); - break; } ciphp->nid = nid; @@ -315,7 +311,7 @@ ossl_rc4_initialize(int argc, VALUE *argv, VALUE self) { ossl_cipher *ciphp = NULL; int spec = 0, nid = 0; - VALUE mode, type; + VALUE mode; GetCipher(self, ciphp); @@ -331,7 +327,6 @@ ossl_rc4_initialize(int argc, VALUE *argv, VALUE self) break; default: rb_raise(rb_eTypeError, "unsupported combination of modes"); - break; } ciphp->nid = nid; @@ -346,7 +341,7 @@ ossl_idea_initialize(int argc, VALUE *argv, VALUE self) { ossl_cipher *ciphp = NULL; int spec = 0, nid = 0; - VALUE mode, type; + VALUE mode; GetCipher(self, ciphp); @@ -368,7 +363,6 @@ ossl_idea_initialize(int argc, VALUE *argv, VALUE self) break; default: rb_raise(rb_eTypeError, "unsupported combination of modes"); - break; } ciphp->nid = nid; @@ -413,7 +407,6 @@ ossl_rc2_initialize(int argc, VALUE *argv, VALUE self) break; default: rb_raise(rb_eTypeError, "unsupported combination of modes"); - break; } ciphp->nid = nid; @@ -428,7 +421,7 @@ ossl_bf_initialize(int argc, VALUE *argv, VALUE self) { ossl_cipher *ciphp = NULL; int spec = 0, nid = 0; - VALUE mode, type; + VALUE mode; GetCipher(self, ciphp); @@ -450,7 +443,6 @@ ossl_bf_initialize(int argc, VALUE *argv, VALUE self) break; default: rb_raise(rb_eTypeError, "unsupported combination of modes"); - break; } ciphp->nid = nid; @@ -465,7 +457,7 @@ ossl_cast5_initialize(int argc, VALUE *argv, VALUE self) { ossl_cipher *ciphp = NULL; int spec = 0, nid = 0; - VALUE mode, type; + VALUE mode; GetCipher(self, ciphp); @@ -487,7 +479,6 @@ ossl_cast5_initialize(int argc, VALUE *argv, VALUE self) break; default: rb_raise(rb_eTypeError, "unsupported combination of modes"); - break; } ciphp->nid = nid; @@ -502,7 +493,7 @@ ossl_rc5_initialize(int argc, VALUE *argv, VALUE self) { ossl_cipher *ciphp = NULL; int spec = 0, nid = 0; - VALUE mode, type; + VALUE mode; GetCipher(self, ciphp); @@ -524,7 +515,6 @@ ossl_rc5_initialize(int argc, VALUE *argv, VALUE self) break; default: rb_raise(rb_eTypeError, "unsupported combination of modes"); - break; } ciphp->nid = nid; @@ -537,7 +527,7 @@ ossl_rc5_initialize(int argc, VALUE *argv, VALUE self) void Init_ossl_cipher(VALUE module) { - eCipherError = rb_define_class_under(module, "Error", rb_eStandardError); + eCipherError = rb_define_class_under(module, "CipherError", rb_eStandardError); cCipher = rb_define_class_under(module, "ANY", rb_cObject); rb_define_singleton_method(cCipher, "new", ossl_cipher_s_new, -1); diff --git a/ossl_config.c b/ossl_config.c index 50f6ed0..4379cd0 100644 --- a/ossl_config.c +++ b/ossl_config.c @@ -82,7 +82,7 @@ ossl_config_initialize(int argc, VALUE* argv, VALUE self) GetConfig(self, configp); rb_scan_args(argc, argv, "10", &path); - Check_Type(path, T_STRING); + Check_SafeStr(path); configp->config = CONF_load(configp->config, RSTRING(path)->ptr, &err_line); @@ -106,10 +106,10 @@ ossl_config_get_string(VALUE self, VALUE section, VALUE item) GetConfig(self, configp); if (!NIL_P(section)) { - Check_Type(section, T_STRING); + Check_SafeStr(section); sect = RSTRING(section)->ptr; } - Check_Type(item, T_STRING); + Check_SafeStr(item); string = CONF_get_string(configp->config, sect, RSTRING(item)->ptr); @@ -126,10 +126,10 @@ ossl_config_get_number(VALUE self, VALUE section, VALUE item) GetConfig(self, configp); if (!NIL_P(section)) { - Check_Type(section, T_STRING); + Check_SafeStr(section); sect = RSTRING(section)->ptr; } - Check_Type(item, T_STRING); + Check_SafeStr(item); number = CONF_get_number(configp->config, sect, RSTRING(item)->ptr); return INT2NUM(number); @@ -145,7 +145,7 @@ ossl_config_get_section(VALUE self, VALUE section) VALUE obj; ossl_configsect_st *ps; - Check_Type(section, T_STRING); + Check_SafeStr(section); GetConfig(self, p); @@ -165,12 +165,14 @@ ossl_config_get_section(VALUE self, VALUE section) * INIT */ void -Init_ossl_config(VALUE mOSSL) +Init_ossl_config(VALUE module) { - eConfigError = rb_define_class_under(mOSSL, "ConfigError", rb_eStandardError); + eConfigError = rb_define_class_under(module, "ConfigError", rb_eStandardError); - cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject); + cConfig = rb_define_class_under(module, "Config", rb_cObject); + rb_define_singleton_method(cConfig, "new", ossl_config_s_new, -1); + rb_define_method(cConfig, "initialize", ossl_config_initialize, -1); rb_define_method(cConfig, "get_string", ossl_config_get_string, 2); rb_define_method(cConfig, "get_number", ossl_config_get_number, 2); diff --git a/ossl_digest.c b/ossl_digest.c index f2013c6..98c878c 100644 --- a/ossl_digest.c +++ b/ossl_digest.c @@ -48,7 +48,6 @@ ossl_digest_get_NID(VALUE obj) ossl_digest *digestp = NULL; OSSL_Check_Type(obj, cDigest); - GetDigest(obj, digestp); return EVP_MD_CTX_type(digestp->md); /*== digestp->md->digest->type*/ @@ -60,7 +59,6 @@ ossl_digest_get_EVP_MD(VALUE obj) ossl_digest *digestp = NULL; OSSL_Check_Type(obj, cDigest); - GetDigest(obj, digestp); return EVP_MD_CTX_md(digestp->md); /*== digestp->md->digest*/ @@ -91,7 +89,8 @@ ossl_digest_update(VALUE self, VALUE data) GetDigest(self, digestp); - Check_Type(data, T_STRING); + Check_SafeStr(data); + EVP_DigestUpdate(digestp->md, RSTRING(data)->ptr, RSTRING(data)->len); return self; @@ -212,7 +211,7 @@ ossl_digest_hexdigest(VALUE self) EVP_DigestInit(digestp->md, EVP_##dgst()); \ \ if (rb_scan_args(argc, argv, "01", &data) == 1) { \ - Check_Type(data, T_STRING); \ + Check_SafeStr(data); \ EVP_DigestUpdate(digestp->md, RSTRING(data)->ptr, RSTRING(data)->len); \ } \ return self; \ @@ -222,25 +221,25 @@ ossl_digest_hexdigest(VALUE self) * Define digest initialize methods */ #ifndef NO_MD2 - DefDigestInit(md2) + DefDigestInit(md2); #endif #ifndef NO_MD4 - DefDigestInit(md4) + DefDigestInit(md4); #endif #ifndef NO_MD5 - DefDigestInit(md5) + DefDigestInit(md5); #endif #ifndef NO_SHA - DefDigestInit(sha) - DefDigestInit(sha1) - DefDigestInit(dss) - DefDigestInit(dss1) + DefDigestInit(sha); + DefDigestInit(sha1); + DefDigestInit(dss); + DefDigestInit(dss1); #endif #ifndef NO_RIPEMD - DefDigestInit(ripemd160) + DefDigestInit(ripemd160); #endif #ifndef NO_MDC2 - DefDigestInit(mdc2) + DefDigestInit(mdc2); #endif /* @@ -249,7 +248,7 @@ ossl_digest_hexdigest(VALUE self) void Init_ossl_digest(VALUE module) { - eDigestError = rb_define_class_under(module, "Error", rb_eStandardError); + eDigestError = rb_define_class_under(module, "DigestError", rb_eStandardError); cDigest = rb_define_class_under(module, "ANY", rb_cObject); rb_define_singleton_method(cDigest, "new", ossl_digest_s_new, -1); @@ -269,8 +268,8 @@ Init_ossl_digest(VALUE module) /* * automation for classes creation and initialize method binding */ -#define DefDigest(name, func) \ - c##name = rb_define_class_under(module, #name, cDigest); \ +#define DefDigest(name, func) \ + c##name = rb_define_class_under(module, #name, cDigest); \ rb_define_method(c##name, "initialize", ossl_##func##_initialize, -1) /* diff --git a/ossl_hmac.c b/ossl_hmac.c index c69c7e7..caf89f0 100644 --- a/ossl_hmac.c +++ b/ossl_hmac.c @@ -70,16 +70,13 @@ ossl_hmac_initialize(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "20", &key, &digest); - OSSL_Check_Type(digest, cDigest); - Check_Type(key, T_STRING); Check_SafeStr(key); + md = ossl_digest_get_EVP_MD(digest); if (!(hmacp->hmac = OPENSSL_malloc(sizeof(HMAC_CTX)))) { rb_raise(eHMACError, "%s", ossl_error()); } - md = ossl_digest_get_EVP_MD(digest); - HMAC_Init(hmacp->hmac, RSTRING(key)->ptr, RSTRING(key)->len, md); return self; @@ -92,7 +89,8 @@ ossl_hmac_update(VALUE self, VALUE data) GetHMAC(self, hmacp); - Check_Type(data, T_STRING); + Check_SafeStr(data); + HMAC_Update(hmacp->hmac, RSTRING(data)->ptr, RSTRING(data)->len); return self; diff --git a/ossl_ns_spki.c b/ossl_ns_spki.c index fed52b3..e9d3b58 100644 --- a/ossl_ns_spki.c +++ b/ossl_ns_spki.c @@ -152,7 +152,6 @@ ossl_spki_set_public_key(VALUE self, VALUE pubk) EVP_PKEY *pkey = NULL; GetSPKI(self, spkip); - OSSL_Check_Type(pubk, cPKey); pkey = ossl_pkey_get_EVP_PKEY(pubk); @@ -161,14 +160,13 @@ ossl_spki_set_public_key(VALUE self, VALUE pubk) rb_raise(eSPKIError, "%s", ossl_error()); } - return self; + return pubk; } static VALUE ossl_spki_get_challenge(VALUE self) { ossl_spki *spkip = NULL; - VALUE str; GetSPKI(self, spkip); @@ -201,15 +199,13 @@ ossl_spki_sign(VALUE self, VALUE key, VALUE digest) const EVP_MD *md = NULL; GetSPKI(self, spkip); - OSSL_Check_Type(key, cPKey); - OSSL_Check_Type(digest, cDigest); + + md = ossl_digest_get_EVP_MD(digest); if (rb_funcall(key, rb_intern("private?"), 0, NULL) == Qfalse) { rb_raise(eSPKIError, "PRIVATE key needed to sign REQ!"); } - pkey = ossl_pkey_get_EVP_PKEY(key); - md = ossl_digest_get_EVP_MD(digest); if (!NETSCAPE_SPKI_sign(spkip->spki, pkey, md)) { EVP_PKEY_free(pkey); @@ -227,18 +223,18 @@ ossl_spki_verify(VALUE self, VALUE key) { ossl_spki *spkip = NULL; EVP_PKEY *pkey = NULL; - int i = 0; + int result = 0; GetSPKI(self, spkip); - OSSL_Check_Type(key, cPKey); pkey = ossl_pkey_get_EVP_PKEY(key); - i = NETSCAPE_SPKI_verify(spkip->spki, pkey); + result = NETSCAPE_SPKI_verify(spkip->spki, pkey); + EVP_PKEY_free(pkey); - if (i < 0) { + if (result < 0) { rb_raise(eSPKIError, "%s", ossl_error()); - } else if (i > 0) + } else if (result > 0) return Qtrue; return Qfalse; diff --git a/ossl_pkcs7.c b/ossl_pkcs7.c index c57eb42..8c09aab 100644 --- a/ossl_pkcs7.c +++ b/ossl_pkcs7.c @@ -87,11 +87,10 @@ ossl_pkcs7si_new_null(void) VALUE obj; MakePKCS7si(obj, p7sip); - - if (!(p7sip->signer = PKCS7_SIGNER_INFO_new())) { - rb_raise(ePKCS7Error, "%s", ossl_error()); - } - + + if (!(p7sip->signer = PKCS7_SIGNER_INFO_new())) + OSSL_Raise(ePKCS7Error, ""); + return obj; } @@ -106,9 +105,8 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *si) MakePKCS7si(obj, p7sip); - if (!(p7sip->signer = PKCS7_SIGNER_INFO_dup(si))) { - rb_raise(ePKCS7Error, "%s", ossl_error()); - } + if (!(p7sip->signer = PKCS7_SIGNER_INFO_dup(si))) + OSSL_Raise(ePKCS7Error, ""); return obj; } @@ -120,12 +118,10 @@ ossl_pkcs7si_get_PKCS7_SIGNER_INFO(VALUE obj) PKCS7_SIGNER_INFO *si = NULL; OSSL_Check_Type(obj, cPKCS7SignerInfo); - GetPKCS7si(obj, p7sip); - if (!(si = PKCS7_SIGNER_INFO_dup(p7sip->signer))) { - rb_raise(ePKCS7Error, "%s", ossl_error()); - } + if (!(si = PKCS7_SIGNER_INFO_dup(p7sip->signer))) + OSSL_Raise(ePKCS7Error, ""); return si; } @@ -146,23 +142,28 @@ static VALUE ossl_pkcs7_s_sign(VALUE klass, VALUE key, VALUE cert, VALUE data) OSSL_Check_Type(key, cPKey); OSSL_Check_Type(cert, X509Certificate); - Check_Type(data, T_STRING); - Check_SafeStr(data); + if (rb_funcall(key, rb_intern("private?"), 0, NULL) != Qtrue) { rb_raise(ePKCS7Error, "private key needed!"); } - + pkey = ossl_pkey_get_EVP_PKEY(key); x509 = ossl_x509_get_X509(cert); - if (!(bio = BIO_new_mem_buf(RSTRING(data)->ptr, -1))) { + if (!(bio = BIO_new_mem_buf(RSTRING(data)->ptr, RSTRING(data)->len))) { + EVP_PKEY_free(pkey); + X509_free(x509); rb_raise(ePKCS7Error, "%s", ossl_error()); } if (!(p7 = PKCS7_sign(x509, pkey, NULL, bio, 0))) { + EVP_PKEY_free(pkey); + X509_free(x509); BIO_free(bio); rb_raise(ePKCS7Error, "%s", ossl_error()); } + EVP_PKEY_free(pkey); + X509_free(x509); BIO_free(bio); MakePKCS7(obj, p7p); @@ -209,7 +210,7 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) break; case T_STRING: Check_SafeStr(arg1); - if (!(in = BIO_new_mem_buf(RSTRING(arg1)->ptr, -1))) { + if (!(in = BIO_new_mem_buf(RSTRING(arg1)->ptr, RSTRING(arg1)->len))) { rb_raise(ePKCS7Error, "%s", ossl_error()); } if (!(p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL))) { @@ -221,6 +222,7 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) default: rb_raise(ePKCS7Error, "unsupported param (%s)", rb_class2name(CLASS_OF(arg1))); } + p7p->pkcs7 = p7; return self; @@ -259,8 +261,8 @@ ossl_pkcs7_add_signer(VALUE self, VALUE signer, VALUE pkey) GetPKCS7(self, p7p); - OSSL_Check_Type(pkey, cPKey); OSSL_Check_Type(signer, cPKCS7SignerInfo); + OSSL_Check_Type(pkey, cPKey); if (rb_funcall(pkey, rb_intern("private?"), 0, NULL) != Qtrue) { rb_raise(ePKCS7Error, "private key needed!"); @@ -270,6 +272,7 @@ ossl_pkcs7_add_signer(VALUE self, VALUE signer, VALUE pkey) si->pkey = key; if (!PKCS7_add_signer(p7p->pkcs7, si)) { + PKCS7_SIGNER_INFO_free(si); rb_raise(ePKCS7Error, "%s", ossl_error()); } @@ -291,7 +294,7 @@ ossl_pkcs7_get_signer(VALUE self) GetPKCS7(self, p7p); if (!(sk = PKCS7_get_signer_info(p7p->pkcs7))) { - rb_warning("OpenSSL::PKCS7 get_signer_info == NULL!"); + rb_warning("OpenSSL::PKCS7#get_signer_info == NULL!"); return rb_ary_new(); } @@ -314,6 +317,7 @@ ossl_pkcs7_add_recipient(VALUE self, VALUE cert) { ossl_pkcs7 *p7p = NULL; PKCS7_RECIP_INFO *ri = NULL; + X509 *x509 = NULL; GetPKCS7(self, p7p); @@ -322,11 +326,16 @@ ossl_pkcs7_add_recipient(VALUE self, VALUE cert) if (!(ri = PKCS7_RECIP_INFO_new())) { rb_raise(ePKCS7Error, "%s", ossl_error()); } - if (!PKCS7_RECIP_INFO_set(ri, ossl_x509_get_X509(cert))) { + + x509 = ossl_x509_get_X509(cert); + + if (!PKCS7_RECIP_INFO_set(ri, x509)) { + X509_free(x509); PKCS7_RECIP_INFO_free(ri); rb_raise(ePKCS7Error, "%s", ossl_error()); } - + X509_free(x509); + if (!PKCS7_add_recipient_info(p7p->pkcs7, ri)) { PKCS7_RECIP_INFO_free(ri); rb_raise(ePKCS7Error, "%s", ossl_error()); @@ -339,30 +348,36 @@ static VALUE ossl_pkcs7_add_certificate(VALUE self, VALUE cert) { ossl_pkcs7 *p7p = NULL; + X509 *x509 = NULL; GetPKCS7(self, p7p); - OSSL_Check_Type(cert, cX509Certificate); + x509 = ossl_x509_get_X509(cert); - if (!PKCS7_add_certificate(p7p->pkcs7, ossl_x509_get_X509(cert))) { + if (!PKCS7_add_certificate(p7p->pkcs7, x509)) { + X509_free(x509); rb_raise(ePKCS7Error, "%s", ossl_error()); } + X509_free(x509); return self; } static VALUE -ossl_pkcs7_add_crl(VALUE self, VALUE crl) +ossl_pkcs7_add_crl(VALUE self, VALUE x509crl) { ossl_pkcs7 *p7p = NULL; - + X509_CRL *crl = NULL; + GetPKCS7(self, p7p); - OSSL_Check_Type(crl, cX509CRL); + crl = ossl_x509crl_get_X509_CRL(x509crl); - if (!PKCS7_add_crl(p7p->pkcs7, ossl_x509crl_get_X509_CRL(crl))) { + if (!PKCS7_add_crl(p7p->pkcs7, crl)) { + X509_CRL_free(crl); rb_raise(ePKCS7Error, "%s", ossl_error()); } + X509_CRL_free(crl); return self; } @@ -379,7 +394,6 @@ ossl_pkcs7_add_data(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "11", &data, &detached); - Check_Type(data, T_STRING); Check_SafeStr(data); PKCS7_content_new(p7p->pkcs7, NID_pkcs7_data); @@ -404,17 +418,17 @@ ossl_pkcs7_add_data(int argc, VALUE *argv, VALUE self) } static VALUE -ossl_pkcs7_data_verify(VALUE self, VALUE x509store, VALUE detached) +ossl_pkcs7_data_verify(int argc, VALUE *argv, VALUE self) { ossl_pkcs7 *p7p = NULL; BIO *bio = NULL, *data = NULL; char buf[1024*4]; - int i = 0; + int i = 0, result; STACK_OF(PKCS7_SIGNER_INFO) *sk = NULL; PKCS7_SIGNER_INFO *si = NULL; X509_STORE *store = NULL; X509_STORE_CTX ctx; - VALUE ary; + VALUE x509store, detached; GetPKCS7(self, p7p); @@ -422,26 +436,28 @@ ossl_pkcs7_data_verify(VALUE self, VALUE x509store, VALUE detached) rb_raise(ePKCS7Error, "Wrong content type - PKCS7 is not SIGNED"); } - OSSL_Check_Type(x509store, cX509Store); - Check_Type(detached, T_STRING); + rb_scan_args(argc, argv, "11", &x509store, &detached); store = ossl_x509store_get_X509_STORE(x509store); - if (!NIL_P(data)) { - if (!(data = BIO_new_mem_buf(RSTRING(detached)->ptr, -1))) { + if (!NIL_P(detached)) { + Check_SafeStr(detached); + if (!(data = BIO_new_mem_buf(RSTRING(detached)->ptr, RSTRING(detached)->len))) rb_raise(ePKCS7Error, "%s", ossl_error()); - } } if (PKCS7_get_detached(p7p->pkcs7)) { if (!data) rb_raise(ePKCS7Error, "PKCS7 is detached, data needed!"); + bio = PKCS7_dataInit(p7p->pkcs7, data); - } else { + } else bio = PKCS7_dataInit(p7p->pkcs7, NULL); - } - if (!bio) + + if (!bio) { + if (data) BIO_free(data); rb_raise(ePKCS7Error, "%s", ossl_error()); + } /* We have to 'read' from bio to calculate digests etc. */ for (;;) { @@ -450,23 +466,22 @@ ossl_pkcs7_data_verify(VALUE self, VALUE x509store, VALUE detached) } /*BIO_free(bio);*/ - sk = PKCS7_get_signer_info(p7p->pkcs7); - if (!sk) { + if (!(sk = PKCS7_get_signer_info(p7p->pkcs7))) rb_raise(ePKCS7Error, "NO SIGNATURES ON THIS DATA"); - } for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sk); i++) { si = sk_PKCS7_SIGNER_INFO_value(sk, i); - i = PKCS7_dataVerify(store, &ctx, bio, p7p->pkcs7, si); - if (i <= 0) { - rb_warn("PKCS7::PKCS7.verify_data(): %s", ossl_error()); + result = PKCS7_dataVerify(store, &ctx, bio, p7p->pkcs7, si); + if (result <= 0) { + rb_warning("PKCS7::PKCS7.verify_data(): %s", ossl_error()); return Qfalse; } /* * Yeld signer info */ - rb_yield(ossl_pkcs7si_new(si)); + if (rb_block_given_p()) + rb_yield(ossl_pkcs7si_new(si)); } return Qtrue; } @@ -498,8 +513,13 @@ ossl_pkcs7_data_decode(VALUE self, VALUE key, VALUE cert) x509 = ossl_x509_get_X509(cert); if (!(bio = PKCS7_dataDecode(p7p->pkcs7, pkey, NULL, x509))) { + EVP_PKEY_free(pkey); + X509_free(x509); rb_raise(ePKCS7Error, "%s", ossl_error()); } + EVP_PKEY_free(pkey); + X509_free(x509); + BIO_get_mem_ptr(bio, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(bio); @@ -559,27 +579,32 @@ ossl_pkcs7si_initialize(int argc, VALUE *argv, VALUE self) GetPKCS7si_unsafe(self, p7sip); - rb_warn("HERE!"); rb_scan_args(argc, argv, "30", &cert, &key, &digest); OSSL_Check_Type(key, cPKey); OSSL_Check_Type(cert, cX509Certificate); - OSSL_Check_Type(digest, cDigest); + md = ossl_digest_get_EVP_MD(digest); if (rb_funcall(key, rb_intern("private?"), 0, NULL) != Qtrue) { rb_raise(ePKCS7Error, "private key needed!"); } pkey = ossl_pkey_get_EVP_PKEY(key); x509 = ossl_x509_get_X509(cert); - md = ossl_digest_get_EVP_MD(digest); if (!(si = PKCS7_SIGNER_INFO_new())) { + EVP_PKEY_free(pkey); + X509_free(x509); rb_raise(ePKCS7Error, "%s", ossl_error()); } if (!(PKCS7_SIGNER_INFO_set(si, x509, pkey, md))) { + EVP_PKEY_free(pkey); + X509_free(x509); PKCS7_SIGNER_INFO_free(si); rb_raise(ePKCS7Error, "%s", ossl_error()); } + EVP_PKEY_free(pkey); + X509_free(x509); + p7sip->signer = si; return self; @@ -626,16 +651,17 @@ ossl_pkcs7si_get_signed_time(VALUE self) * INIT */ void -Init_pkcs7(VALUE mPKCS7) +Init_pkcs7(VALUE module) { - ePKCS7Error = rb_define_class_under(mPKCS7, "Error", rb_eStandardError); + ePKCS7Error = rb_define_class_under(module, "PKCS7Error", rb_eStandardError); - cPKCS7 = rb_define_class_under(mPKCS7, "PKCS7", rb_cObject); + cPKCS7 = rb_define_class_under(module, "PKCS7", rb_cObject); /* * WORKS WELL, but we can implement this in Ruby space * rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, 3); */ rb_define_singleton_method(cPKCS7, "new", ossl_pkcs7_s_new, -1); + rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 2); rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0); @@ -644,18 +670,20 @@ Init_pkcs7(VALUE mPKCS7) rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1); rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1); rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, -1); - rb_define_method(cPKCS7, "verify_data", ossl_pkcs7_data_verify, 2); + rb_define_method(cPKCS7, "verify_data", ossl_pkcs7_data_verify, -1); rb_define_method(cPKCS7, "decode_data", ossl_pkcs7_data_decode, 2); rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); -#define DefPKCS7Const(x) rb_define_const(mPKCS7, #x, INT2FIX(x)) +#define DefPKCS7Const(x) rb_define_const(module, #x, INT2FIX(x)) DefPKCS7Const(SIGNED); DefPKCS7Const(ENVELOPED); DefPKCS7Const(SIGNED_ENVELOPED); - cPKCS7SignerInfo = rb_define_class_under(mPKCS7, "Signer", rb_cObject); + cPKCS7SignerInfo = rb_define_class_under(module, "Signer", rb_cObject); + rb_define_singleton_method(cPKCS7SignerInfo, "new", ossl_pkcs7si_s_new, -1); + rb_define_method(cPKCS7SignerInfo, "initialize", ossl_pkcs7si_initialize, -1); rb_define_method(cPKCS7SignerInfo, "name", ossl_pkcs7si_get_name, 0); rb_define_method(cPKCS7SignerInfo, "serial", ossl_pkcs7si_get_serial, 0); diff --git a/ossl_pkey.c b/ossl_pkey.c index 91005d8..53dbe76 100644 --- a/ossl_pkey.c +++ b/ossl_pkey.c @@ -59,6 +59,8 @@ ossl_pkey_new_from_file(VALUE path) EVP_PKEY *pkey = NULL; VALUE obj; + Check_SafeStr(path); + filename = RSTRING(path)->ptr; if ((fp = fopen(filename, "r")) == NULL) rb_raise(ePKeyError, "%s", strerror(errno)); @@ -82,7 +84,6 @@ ossl_pkey_get_EVP_PKEY(VALUE obj) ossl_pkey *pkeyp = NULL; OSSL_Check_Type(obj, cPKey); - GetPKey(obj, pkeyp); return pkeyp->get_EVP_PKEY(obj); @@ -94,9 +95,6 @@ ossl_pkey_get_EVP_PKEY(VALUE obj) static VALUE ossl_pkey_s_new(int argc, VALUE *argv, VALUE klass) { - ossl_pkey *pkeyp = NULL; - VALUE obj; - if (klass == cPKey) rb_raise(rb_eNotImpError, "cannot do PKey::ANY.new - it is an abstract class"); @@ -109,7 +107,7 @@ ossl_pkey_s_new(int argc, VALUE *argv, VALUE klass) void Init_ossl_pkey(VALUE module) { - ePKeyError = rb_define_class_under(module, "Error", rb_eStandardError); + ePKeyError = rb_define_class_under(module, "PKeyError", rb_eStandardError); cPKey = rb_define_class_under(module, "ANY", rb_cObject); rb_define_singleton_method(cPKey, "new", ossl_pkey_s_new, -1); diff --git a/ossl_pkey_dsa.c b/ossl_pkey_dsa.c index 370be8a..6586fe1 100644 --- a/ossl_pkey_dsa.c +++ b/ossl_pkey_dsa.c @@ -17,9 +17,9 @@ obj = Data_Make_Struct(cDSA, ossl_dsa, 0, ossl_dsa_free, dsap);\ dsap->pkey.get_EVP_PKEY = ossl_dsa_get_EVP_PKEY;\ } -#define GetDSA_unsafe(obj, dsap) Data_Get_Struct(obj, ossl_dsa, dsap) + #define GetDSA(obj, dsap) {\ - GetDSA_unsafe(obj, dsap);\ + Data_Get_Struct(obj, ossl_dsa, dsap);\ if (!dsap->dsa) rb_raise(eDSAError, "not initialized!");\ } @@ -92,7 +92,6 @@ ossl_dsa_get_DSA(VALUE obj) DSA *dsa = NULL; OSSL_Check_Type(obj, cDSA); - GetDSA(obj, dsap); dsa = (DSA_PRIVATE(dsap->dsa)) ? DSAPrivateKey_dup(dsap->dsa) : DSAPublicKey_dup(dsap->dsa); @@ -108,8 +107,6 @@ ossl_dsa_get_EVP_PKEY(VALUE obj) DSA *dsa = NULL; EVP_PKEY *pkey = NULL; - OSSL_Check_Type(obj, cDSA); - dsa = ossl_dsa_get_DSA(obj); if (!(pkey = EVP_PKEY_new())) { @@ -117,8 +114,9 @@ ossl_dsa_get_EVP_PKEY(VALUE obj) rb_raise(eDSAError, "%s", ossl_error()); } - if (!EVP_PKEY_assign_DSA(pkey, dsa)) { + if (!EVP_PKEY_assign_DSA(pkey, dsa)) { /* NO DUP - don't free! */ DSA_free(dsa); + EVP_PKEY_free(pkey); rb_raise(eDSAError, "%s", ossl_error()); } @@ -129,14 +127,39 @@ ossl_dsa_get_EVP_PKEY(VALUE obj) * Private */ static VALUE -ossl_dsa_s_new(int argc, VALUE *argv, VALUE klass) +ossl_dsa_s_new_from_pem(int argc, VALUE *argv, VALUE klass) { ossl_dsa *dsap = NULL; - VALUE obj; + DSA *dsa = NULL; + BIO *in = NULL; + char *passwd = NULL; + VALUE buffer, pass, obj; - MakeDSA(obj, dsap); + rb_scan_args(argc, argv, "11", &buffer, &pass); + + Check_SafeStr(buffer); + + if (!NIL_P(pass)) { + Check_SafeStr(pass); + passwd = RSTRING(pass)->ptr; + } + /* else passwd = NULL; */ + + if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) + OSSL_Raise(eDSAError, ""); - rb_obj_call_init(obj, argc, argv); + if (!(dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL))) { + BIO_reset(in); + + if (!(dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, passwd))) { + BIO_free(in); + OSSL_Raise(eDSAError, "Neither PUB key nor PRIV key:"); + } + } + BIO_free(in); + + MakeDSA(obj, dsap); + dsap->dsa = dsa; return obj; } @@ -157,71 +180,36 @@ ossl_dsa_generate_cb(int p, int n, void *arg) } static VALUE -ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) +ossl_dsa_s_generate(VALUE klass, VALUE size) { ossl_dsa *dsap = NULL; DSA *dsa = NULL; unsigned char seed[20]; int seed_len = 20, counter = 0; unsigned long h = 0; - BIO *in = NULL; - char *passwd = NULL; void (*cb)(int, int, void *) = NULL; - VALUE buffer, pass; + VALUE obj; - GetDSA_unsafe(self, dsap); - - rb_scan_args(argc, argv, "02", &buffer, &pass); + Check_Type(size, T_FIXNUM); - if (NIL_P(buffer)) { - if (!(dsa = DSA_new())) { - rb_raise(eDSAError, "%s", ossl_error()); - } - } else switch (TYPE(buffer)) { - case T_FIXNUM: - if (!RAND_bytes(seed, seed_len)) { - rb_raise(eDSAError, "%s", ossl_error()); - } - if (rb_block_given_p()) - cb = ossl_dsa_generate_cb; - - if (!(dsa = DSA_generate_parameters(FIX2INT(buffer), seed, seed_len, &counter, &h, cb, NULL))) { /* arg to cb = NULL */ - rb_raise(eDSAError, "%s", ossl_error()); - } - if (!DSA_generate_key(dsa)) { - DSA_free(dsa); - rb_raise(eDSAError, "%s", ossl_error()); - } - break; - case T_STRING: - Check_SafeStr(buffer); - if (NIL_P(pass)) - passwd = NULL; - else { - Check_SafeStr(pass); - passwd = RSTRING(pass)->ptr; - } - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, -1))) { - rb_raise(eDSAError, "%s", ossl_error()); - } - if (!(dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL))) { - BIO_free(in); - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, -1))) { - rb_raise(eDSAError, "%s", ossl_error()); - } - if (!(dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, passwd))) { - BIO_free(in); - rb_raise(eDSAError, "%s", ossl_error()); - } - } - BIO_free(in); - break; - default: - rb_raise(eDSAError, "unsupported argument (%s)", rb_class2name(CLASS_OF(buffer))); + if (!RAND_bytes(seed, seed_len)) + rb_raise(eDSAError, "%s", ossl_error()); + + if (rb_block_given_p()) + cb = ossl_dsa_generate_cb; + + if (!(dsa = DSA_generate_parameters(FIX2INT(size), seed, seed_len, &counter, &h, cb, NULL))) { /* arg to cb = NULL */ + OSSL_Raise(eDSAError, ""); } + if (!DSA_generate_key(dsa)) { + DSA_free(dsa); + rb_raise(eDSAError, "%s", ossl_error()); + } + + MakeDSA(obj, dsap); dsap->dsa = dsa; - return self; + return obj; } static VALUE @@ -263,7 +251,6 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "02", &cipher, &password); if (!NIL_P(cipher)) { - OSSL_Check_Type(cipher, cCipher); ciph = ossl_cipher_get_EVP_CIPHER(cipher); if (!NIL_P(password)) { @@ -297,43 +284,34 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) static VALUE ossl_dsa_to_der(VALUE self) { - ossl_dsa *dsap = NULL; DSA *dsa = NULL; EVP_PKEY *pkey = NULL; X509_PUBKEY *key = NULL; VALUE str; - GetDSA(self, dsap); - - dsa = (DSA_PRIVATE(dsap->dsa)) ? DSAPrivateKey_dup(dsap->dsa):DSAPublicKey_dup(dsap->dsa); - - if (!dsa) - rb_raise(eDSAError, "%s", ossl_error()); + dsa = ossl_dsa_get_DSA(self); if (!(pkey = EVP_PKEY_new())) { DSA_free(dsa); rb_raise(eDSAError, "%s", ossl_error()); } - if (!EVP_PKEY_assign_DSA(pkey, dsap->dsa)) { - /*DSA_free(dsa);*/ + if (!EVP_PKEY_assign_DSA(pkey, dsa)) { /* NO DUP - don't free! */ + DSA_free(dsa); EVP_PKEY_free(pkey); rb_raise(eDSAError, "%s", ossl_error()); } if (!(key = X509_PUBKEY_new())) { - /*DSA_free(dsa);*/ EVP_PKEY_free(pkey); rb_raise(eDSAError, "%s", ossl_error()); } - if (!X509_PUBKEY_set(&key, pkey)) { - /*DSA_free(dsa);*/ - /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free!! */ + if (!X509_PUBKEY_set(&key, pkey)) { /* safe to FREE pkey or NOT? */ + EVP_PKEY_free(pkey); X509_PUBKEY_free(key); rb_raise(eDSAError, "%s", ossl_error()); } str = rb_str_new(key->public_key->data, key->public_key->length); - /*DSA_free(dsa);*/ - /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free!! */ + /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free?? */ X509_PUBKEY_free(key); return str; @@ -361,8 +339,8 @@ ossl_dsa_to_str(VALUE self) BIO_free(out); rb_raise(eDSAError, "%s", ossl_error()); } - BIO_get_mem_ptr(out, &buf); + BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -381,6 +359,7 @@ ossl_dsa_to_public_key(VALUE self) GetDSA(self, dsap1); MakeDSA(obj, dsap2); + if (!(dsap2->dsa = DSAPublicKey_dup(dsap1->dsa))) { rb_raise(eDSAError, "%s", ossl_error()); } @@ -411,7 +390,6 @@ ossl_dsa_sign(VALUE self, VALUE data) OPENSSL_free(sig); rb_raise(eDSAError, "%s", ossl_error()); } - str = rb_str_new(sig, sig_len); OPENSSL_free(sig); @@ -425,16 +403,18 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) int ret = -1; GetDSA(self, dsap); + Check_SafeStr(digest); Check_SafeStr(sig); - ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len, RSTRING(sig)->ptr, RSTRING(sig)->len, dsap->dsa); /*type = 0*/ + ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len,\ + RSTRING(sig)->ptr, RSTRING(sig)->len, dsap->dsa); /*type = 0*/ if (ret < 0) rb_raise(eDSAError, "%s", ossl_error()); - - if (ret == 1) + else if (ret == 1) return Qtrue; + return Qfalse; } @@ -447,8 +427,11 @@ Init_ossl_dsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError); cDSA = rb_define_class_under(mPKey, "DSA", cPKey); - rb_define_singleton_method(cDSA, "new", ossl_dsa_s_new, -1); - rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1); + + rb_define_singleton_method(cDSA, "new_from_pem", ossl_dsa_s_new_from_pem, -1); + rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1); + rb_define_alias(CLASS_OF(cDSA), "new_from_fixnum", "generate"); + rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); rb_define_method(cDSA, "to_str", ossl_dsa_to_str, 0); diff --git a/ossl_pkey_rsa.c b/ossl_pkey_rsa.c index f5e75c5..66ffa79 100644 --- a/ossl_pkey_rsa.c +++ b/ossl_pkey_rsa.c @@ -17,9 +17,9 @@ obj = Data_Make_Struct(cRSA, ossl_rsa, 0, ossl_rsa_free, rsap);\ rsap->pkey.get_EVP_PKEY = ossl_rsa_get_EVP_PKEY;\ } -#define GetRSA_unsafe(obj, rsap) Data_Get_Struct(obj, ossl_rsa, rsap) + #define GetRSA(obj, rsap) {\ - GetRSA_unsafe(obj, rsap);\ + Data_Get_Struct(obj, ossl_rsa, rsap);\ if (!rsap->rsa) rb_raise(eRSAError, "not initialized!");\ } @@ -92,7 +92,6 @@ ossl_rsa_get_RSA(VALUE obj) RSA *rsa = NULL; OSSL_Check_Type(obj, cRSA); - GetRSA(obj, rsap); rsa = (RSA_PRIVATE(rsap->rsa)) ? RSAPrivateKey_dup(rsap->rsa) : RSAPublicKey_dup(rsap->rsa); @@ -109,8 +108,6 @@ ossl_rsa_get_EVP_PKEY(VALUE obj) RSA *rsa = NULL; EVP_PKEY *pkey = NULL; - OSSL_Check_Type(obj, cRSA); - rsa = ossl_rsa_get_RSA(obj); if (!(pkey = EVP_PKEY_new())) { @@ -120,6 +117,7 @@ ossl_rsa_get_EVP_PKEY(VALUE obj) if (!EVP_PKEY_assign_RSA(pkey, rsa)) { RSA_free(rsa); + EVP_PKEY_free(pkey); rb_raise(eRSAError, "%s", ossl_error()); } @@ -130,14 +128,39 @@ ossl_rsa_get_EVP_PKEY(VALUE obj) * Private */ static VALUE -ossl_rsa_s_new(int argc, VALUE *argv, VALUE klass) +ossl_rsa_s_new_from_pem(int argc, VALUE *argv, VALUE klass) { ossl_rsa *rsap = NULL; - VALUE obj; + RSA *rsa = NULL; + BIO *in = NULL; + char *passwd = NULL; + VALUE buffer, pass, obj; - MakeRSA(obj, rsap); + rb_scan_args(argc, argv, "11", &buffer, &pass); + + Check_SafeStr(buffer); + + if (!NIL_P(pass)) { + Check_SafeStr(pass); + passwd = RSTRING(pass)->ptr; + } + /* else passwd = NULL; */ + + if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) + rb_raise(eRSAError, "%s", ossl_error()); + + if (!(rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL))) { + BIO_reset(in); + + if (!(rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, passwd))) { + BIO_free(in); + OSSL_Raise(eRSAError, "Neither PUB key nor PRIV key:"); + } + } + BIO_free(in); - rb_obj_call_init(obj, argc, argv); + MakeRSA(obj, rsap); + rsap->rsa = rsa; return obj; } @@ -158,62 +181,26 @@ ossl_rsa_generate_cb(int p, int n, void *arg) } static VALUE -ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) +ossl_rsa_s_generate(VALUE klass, VALUE size) { ossl_rsa *rsap = NULL; RSA *rsa = NULL; - int type = 0; - BIO *in = NULL; - char *passwd = NULL; void (*cb)(int, int, void *) = NULL; - VALUE buffer, pass; + VALUE obj; - GetRSA_unsafe(self, rsap); - - rb_scan_args(argc, argv, "02", &buffer, &pass); + Check_Type(size, T_FIXNUM); - if (NIL_P(buffer)) { - if (!(rsa = RSA_new())) { - rb_raise(eRSAError, "%s", ossl_error()); - } - } else switch (TYPE(buffer)) { - case T_FIXNUM: - if (rb_block_given_p()) - cb = ossl_rsa_generate_cb; - if (!(rsa = RSA_generate_key(FIX2INT(buffer), RSA_F4, cb, NULL))) { /* arg to cb = NULL */ - rb_raise(eRSAError, "%s", ossl_error()); - } - break; - case T_STRING: - Check_SafeStr(buffer); - if (NIL_P(pass)) - passwd = NULL; - else { - pass = rb_str_to_str(pass); - Check_SafeStr(pass); - passwd = RSTRING(pass)->ptr; - } - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, -1))) { - rb_raise(eRSAError, "%s", ossl_error()); - } - if (!(rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL))) { - BIO_free(in); - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, -1))) { - rb_raise(eRSAError, "%s", ossl_error()); - } - if (!(rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, passwd))) { - BIO_free(in); - rb_raise(eRSAError, "%s", ossl_error()); - } - } - BIO_free(in); - break; - default: - rb_raise(eRSAError, "unsupported argument (%s)", rb_class2name(CLASS_OF(buffer))); + if (rb_block_given_p()) + cb = ossl_rsa_generate_cb; + + if (!(rsa = RSA_generate_key(FIX2INT(size), RSA_F4, cb, NULL))) { /* arg to cb = NULL */ + rb_raise(eRSAError, "%s", ossl_error()); } + + MakeRSA(obj, rsap); rsap->rsa = rsa; - return self; + return obj; } static VALUE @@ -255,7 +242,6 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "02", &cipher, &password); if (!NIL_P(cipher)) { - OSSL_Check_Type(cipher, cCipher); ciph = ossl_cipher_get_EVP_CIPHER(cipher); if (!NIL_P(password)) { @@ -296,12 +282,13 @@ ossl_rsa_public_encrypt(VALUE self, VALUE buffer) GetRSA(self, rsap); - Check_Type(buffer, T_STRING); + Check_SafeStr(buffer); + size = RSA_size(rsap->rsa); - if (!(enc_text = OPENSSL_malloc(size + 16))) { - rb_raise(eRSAError, "Memory alloc error"); - } + if (!(enc_text = OPENSSL_malloc(size + 16))) + OSSL_Raise(eRSAError, ""); + if ((len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, enc_text, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { OPENSSL_free(enc_text); rb_raise(eRSAError, "%s", ossl_error()); @@ -322,12 +309,13 @@ ossl_rsa_public_decrypt(VALUE self, VALUE buffer) GetRSA(self, rsap); - Check_Type(buffer, T_STRING); + Check_SafeStr(buffer); + size = RSA_size(rsap->rsa); - if (!(txt = OPENSSL_malloc(size + 16))) { - rb_raise(eRSAError, "Memory alloc error"); - } + if (!(txt = OPENSSL_malloc(size + 16))) + OSSL_Raise(eRSAError, ""); + if ((len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, txt, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { OPENSSL_free(txt); rb_raise(eRSAError, "%s", ossl_error()); @@ -349,16 +337,16 @@ ossl_rsa_private_encrypt(VALUE self, VALUE buffer) GetRSA(self, rsap); if (!RSA_PRIVATE(rsap->rsa)) { - rb_raise(eRSAError, "This key is PUBLIC only!"); + rb_raise(eRSAError, "PRIVATE key needed for this operation!"); } - Check_Type(buffer, T_STRING); + Check_SafeStr(buffer); size = RSA_size(rsap->rsa); - if (!(enc_text = OPENSSL_malloc(size + 16))) { - rb_raise(eRSAError, "Memory alloc error"); - } + if (!(enc_text = OPENSSL_malloc(size + 16))) + OSSL_Raise(eRSAError, "Memory alloc error"); + if ((len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, enc_text, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { OPENSSL_free(enc_text); rb_raise(eRSAError, "%s", ossl_error()); @@ -382,16 +370,17 @@ ossl_rsa_private_decrypt(VALUE self, VALUE buffer) if (!RSA_PRIVATE(rsap->rsa)) { rb_raise(eRSAError, "Private RSA key needed!"); } - Check_Type(buffer, T_STRING); + + Check_SafeStr(buffer); size = RSA_size(rsap->rsa); - if (!(txt = OPENSSL_malloc(size + 16))) { - rb_raise(eRSAError, "Memory alloc error"); - } + if (!(txt = OPENSSL_malloc(size + 16))) + OSSL_Raise(eRSAError, "Memory alloc error"); + if ((len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, txt, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { OPENSSL_free(txt); - rb_raise(eRSAError, "%s", ossl_error()); + OSSL_Raise(eRSAError, ""); } text = rb_str_new(txt, len); OPENSSL_free(txt); @@ -402,7 +391,8 @@ ossl_rsa_private_decrypt(VALUE self, VALUE buffer) /* * Just sample * (it's not (maybe) wise to show private RSA values) - */ + * - if, then implement this via OpenSSL::BN + * static VALUE ossl_rsa_get_n(VALUE self) { @@ -420,54 +410,46 @@ ossl_rsa_get_n(VALUE self) BIO_free(out); rb_raise(eRSAError, "%s", ossl_error()); } - BIO_get_mem_ptr(out, &buf); + BIO_get_mem_ptr(out, &buf); num = rb_cstr2inum(buf->data, 16); BIO_free(out); return num; } + */ static VALUE ossl_rsa_to_der(VALUE self) { - ossl_rsa *rsap = NULL; RSA *rsa = NULL; EVP_PKEY *pkey = NULL; X509_PUBKEY *key = NULL; VALUE str; - GetRSA(self, rsap); - - rsa = (RSA_PRIVATE(rsap->rsa)) ? RSAPrivateKey_dup(rsap->rsa):RSAPublicKey_dup(rsap->rsa); - - if (!rsa) - rb_raise(eRSAError, "%s", ossl_error()); + rsa = ossl_rsa_get_RSA(self); if (!(pkey = EVP_PKEY_new())) { RSA_free(rsa); rb_raise(eRSAError, "%s", ossl_error()); } - if (!EVP_PKEY_assign_RSA(pkey, rsap->rsa)) { - /*RSA_free(rsa);*/ + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { /* NO DUP - don't free! */ + RSA_free(rsa); EVP_PKEY_free(pkey); rb_raise(eRSAError, "%s", ossl_error()); - } + } if (!(key = X509_PUBKEY_new())) { - /*RSA_free(rsa);*/ EVP_PKEY_free(pkey); rb_raise(eRSAError, "%s", ossl_error()); } - if (!X509_PUBKEY_set(&key, pkey)) { - /*RSA_free(rsa);*/ - /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free!! */ + if (!X509_PUBKEY_set(&key, pkey)) { /* safe to FREE pkey??? */ + EVP_PKEY_free(pkey); X509_PUBKEY_free(key); rb_raise(eRSAError, "%s", ossl_error()); } str = rb_str_new(key->public_key->data, key->public_key->length); - /*RSA_free(rsa);*/ - /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free!! */ + /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free?? */ X509_PUBKEY_free(key); return str; @@ -495,8 +477,8 @@ ossl_rsa_to_str(VALUE self) BIO_free(out); rb_raise(eRSAError, "%s", ossl_error()); } - BIO_get_mem_ptr(out, &buf); + BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -515,6 +497,7 @@ ossl_rsa_to_public_key(VALUE self) GetRSA(self, rsap1); MakeRSA(obj, rsap2); + if (!(rsap2->rsa = RSAPublicKey_dup(rsap1->rsa))) { rb_raise(eRSAError, "%s", ossl_error()); } @@ -572,8 +555,10 @@ Init_ossl_rsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError); cRSA = rb_define_class_under(mPKey, "RSA", cPKey); - rb_define_singleton_method(cRSA, "new", ossl_rsa_s_new, -1); - rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1); + + rb_define_singleton_method(cRSA, "new_from_pem", ossl_rsa_s_new_from_pem, -1); + rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, 1); + rb_define_alias(CLASS_OF(cRSA), "new_from_fixnum", "generate"); rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0); rb_define_method(cRSA, "to_str", ossl_rsa_to_str, 0); @@ -584,7 +569,7 @@ Init_ossl_rsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, 1); rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, 1); rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, 1); - rb_define_method(cRSA, "n", ossl_rsa_get_n, 0); + /*rb_define_method(cRSA, "n", ossl_rsa_get_n, 0);*/ rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0); /* * Implemented in Ruby space... diff --git a/ossl_rand.c b/ossl_rand.c index 424a918..60b9af4 100644 --- a/ossl_rand.c +++ b/ossl_rand.c @@ -85,15 +85,16 @@ ossl_rand_bytes(VALUE self, VALUE len) * INIT */ void -Init_ossl_rand(VALUE mOSSL) +Init_ossl_rand(VALUE module) { - rb_define_method(mOSSL, "seed", ossl_rand_seed, 1); - rb_define_method(mOSSL, "load_random_file", ossl_rand_load_file, 1); - rb_define_method(mOSSL, "write_random_file", ossl_rand_write_file, 1); + rb_define_method(module, "seed", ossl_rand_seed, 1); + rb_define_method(module, "load_random_file", ossl_rand_load_file, 1); + rb_define_method(module, "write_random_file", ossl_rand_write_file, 1); - eRandomError = rb_define_class_under(mOSSL, "RandomError", rb_eStandardError); + eRandomError = rb_define_class_under(module, "RandomError", rb_eStandardError); - cRandom = rb_define_class_under(mOSSL, "Random", rb_cObject); + cRandom = rb_define_class_under(module, "Random", rb_cObject); + rb_define_method(cRandom, "seed", ossl_rand_seed, 1); rb_define_method(cRandom, "load_random_file", ossl_rand_load_file, 1); rb_define_method(cRandom, "write_random_file", ossl_rand_write_file, 1); @@ -35,8 +35,6 @@ #define numberof(ary) (sizeof(ary)/sizeof((ary)[0])) -#define ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x)) - #define ssl_get_io(o) rb_ivar_get((o),rb_intern("@io")) #define ssl_get_cert(o) rb_ivar_get((o),rb_intern("@cert")) #define ssl_get_cert_file(o) rb_ivar_get((o),rb_intern("@cert_file")) @@ -95,8 +93,7 @@ typedef struct ssl_st_t{ } ssl_st; static void -ssl_shutdown(p) - ssl_st *p; +ssl_shutdown(ssl_st *p) { if(p->ssl){ SSL_shutdown(p->ssl); @@ -105,18 +102,20 @@ ssl_shutdown(p) } static void -ssl_free(p) - ssl_st *p; +ssl_free(ssl_st *p) { ssl_shutdown(p); SSL_free(p->ssl); + p->ssl = NULL; SSL_CTX_free(p->ctx); + p->ctx = NULL; free(p); } static VALUE ssl_verify_callback_proc; -static VALUE ssl_call_callback_proc(VALUE args) +static VALUE +ssl_call_callback_proc(VALUE args) { VALUE proc, ok, x509stc; @@ -131,21 +130,25 @@ static VALUE ssl_call_callback_proc(VALUE args) * for rb_rescue in ssl_verify_callback * see below */ -static VALUE ssl_false(VALUE dummy) +static VALUE +ssl_false(VALUE dummy) { return Qfalse; } -static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) +static int +ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { VALUE x509stc, args, ret; + ret = (ok) ? Qtrue : Qfalse; + if (!NIL_P(ssl_verify_callback_proc)) { x509stc = ossl_x509store_new(ctx); rb_funcall(x509stc, rb_intern("protect"), 0, NULL); args = rb_ary_new2(3); rb_ary_store(args, 0, ssl_verify_callback_proc); - rb_ary_store(args, 1, ok ? Qtrue : Qfalse); + rb_ary_store(args, 1, ret); rb_ary_store(args, 2, x509stc); ret = rb_rescue(ssl_call_callback_proc, args, ssl_false, Qnil); } @@ -153,7 +156,8 @@ static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) return (ret == Qtrue) ? 1 : 0; } -static void ssl_ctx_setup(VALUE self) +static void +ssl_ctx_setup(VALUE self) { ssl_st *p = NULL; X509 *cert = NULL, *ca = NULL; @@ -187,8 +191,8 @@ static void ssl_ctx_setup(VALUE self) if (ca) if(!SSL_CTX_add_client_CA(p->ctx, ca)) rb_raise(eSSLError, "%s", ossl_error()); - if (!SSL_CTX_load_verify_locations(p->ctx, ca_file, ca_path) || - !SSL_CTX_set_default_verify_paths(p->ctx) && + if ((!SSL_CTX_load_verify_locations(p->ctx, ca_file, ca_path) || + !SSL_CTX_set_default_verify_paths(p->ctx)) && ruby_verbose) { rb_warning("can't set verify locations:%s", ossl_error()); } @@ -204,7 +208,8 @@ static void ssl_ctx_setup(VALUE self) if(!NIL_P(val)) SSL_CTX_set_verify_depth(p->ctx, NUM2LONG(val)); } -static void ssl_setup(VALUE self) +static void +ssl_setup(VALUE self) { ssl_st *p; VALUE io; @@ -223,10 +228,7 @@ static void ssl_setup(VALUE self) } static VALUE -ssl_s_new(argc, argv, klass) - int argc; - VALUE *argv; - VALUE klass; +ssl_s_new(int argc, VALUE *argv, VALUE klass) { VALUE obj; ssl_st *p; @@ -242,7 +244,8 @@ ssl_s_new(argc, argv, klass) return obj; } -static VALUE ssl_initialize(int argc, VALUE *argv, VALUE self) +static VALUE +ssl_initialize(int argc, VALUE *argv, VALUE self) { VALUE io, key, cert; @@ -273,7 +276,8 @@ static VALUE ssl_initialize(int argc, VALUE *argv, VALUE self) return self; } -static VALUE ssl_connect(VALUE self) +static VALUE +ssl_connect(VALUE self) { ssl_st *p; @@ -290,8 +294,7 @@ static VALUE ssl_connect(VALUE self) } static VALUE -ssl_accept(self) - VALUE self; +ssl_accept(VALUE self) { ssl_st *p; @@ -308,14 +311,11 @@ ssl_accept(self) } static VALUE -ssl_read(self, len) - VALUE self, len; +ssl_read(VALUE self, VALUE len) { ssl_st *p; size_t ilen, nread = 0; - char *buf; VALUE str; - int iostate = 1; OpenFile *fptr; Data_Get_Struct(self, ssl_st, p); @@ -345,8 +345,7 @@ ssl_read(self, len) } static VALUE -ssl_write(self, str) - VALUE self, str; +ssl_write(VALUE self, VALUE str) { ssl_st *p; size_t nwrite = 0; @@ -374,8 +373,7 @@ ssl_write(self, str) } static VALUE -ssl_close(self) - VALUE self; +ssl_close(VALUE self) { ssl_st *p; @@ -385,8 +383,7 @@ ssl_close(self) } static VALUE -ssl_get_certificate(self) - VALUE self; +ssl_get_certificate(VALUE self) { ssl_st *p; X509 *cert = NULL; @@ -403,8 +400,7 @@ ssl_get_certificate(self) } static VALUE -ssl_get_peer_certificate(self) - VALUE self; +ssl_get_peer_certificate(VALUE self) { ssl_st *p; X509 *cert = NULL; @@ -421,8 +417,7 @@ ssl_get_peer_certificate(self) } static VALUE -ssl_cipher_to_ary(cipher) - SSL_CIPHER *cipher; +ssl_cipher_to_ary(SSL_CIPHER *cipher) { VALUE ary; int bits, alg_bits; @@ -438,8 +433,7 @@ ssl_cipher_to_ary(cipher) } static VALUE -ssl_get_cipher(self) - VALUE self; +ssl_get_cipher(VALUE self) { ssl_st *p; SSL_CIPHER *cipher; @@ -455,8 +449,7 @@ ssl_get_cipher(self) } static VALUE -ssl_get_ciphers(self) - VALUE self; +ssl_get_ciphers(VALUE self) { ssl_st *p; STACK_OF(SSL_CIPHER) *ciphers; @@ -481,11 +474,10 @@ ssl_get_ciphers(self) } static VALUE -ssl_set_ciphers(self, v) - VALUE self, v; +ssl_set_ciphers(VALUE self, VALUE v) { ssl_st *p; - VALUE str, s, elem; + VALUE str, elem; int i; Data_Get_Struct(self, ssl_st, p); @@ -514,8 +506,7 @@ ssl_set_ciphers(self, v) } static VALUE -ssl_get_state(self) - VALUE self; +ssl_get_state(VALUE self) { ssl_st *p; VALUE ret; @@ -533,7 +524,8 @@ ssl_get_state(self) return ret; } -static VALUE ssl_set_cert2(VALUE self, VALUE v) +static VALUE +ssl_set_cert2(VALUE self, VALUE v) { if(!NIL_P(v)) OSSL_Check_Type(v, cX509Certificate); ssl_set_cert(self, v); @@ -541,7 +533,8 @@ static VALUE ssl_set_cert2(VALUE self, VALUE v) return v; } -static VALUE ssl_set_cert_file2(VALUE self, VALUE v) +static VALUE +ssl_set_cert_file2(VALUE self, VALUE v) { VALUE cert; cert = NIL_P(v) ? Qnil :ossl_x509_new_from_file(v); @@ -550,7 +543,8 @@ static VALUE ssl_set_cert_file2(VALUE self, VALUE v) return v; } -static VALUE ssl_set_key2(VALUE self, VALUE v) +static VALUE +ssl_set_key2(VALUE self, VALUE v) { if(!NIL_P(v)) OSSL_Check_Type(v, cPKey); ssl_set_key(self, v); @@ -558,7 +552,8 @@ static VALUE ssl_set_key2(VALUE self, VALUE v) return v; } -static VALUE ssl_set_key_file2(VALUE self, VALUE v) +static VALUE +ssl_set_key_file2(VALUE self, VALUE v) { VALUE key; key = NIL_P(v) ? Qnil : ossl_pkey_new_from_file(v); @@ -567,15 +562,16 @@ static VALUE ssl_set_key_file2(VALUE self, VALUE v) return v; } -void Init_ssl(VALUE mSSL) +void +Init_ssl(VALUE module) { int i; /* class SSLError */ - eSSLError = rb_define_class_under(mSSL, "Error", rb_eStandardError); + eSSLError = rb_define_class_under(module, "Error", rb_eStandardError); /* class SSLSocket */ - cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject); + cSSLSocket = rb_define_class_under(module, "SSLSocket", rb_cObject); rb_define_singleton_method(cSSLSocket, "new", ssl_s_new, -1); rb_define_method(cSSLSocket, "initialize", ssl_initialize, -1); rb_define_method(cSSLSocket, "__connect", ssl_connect, 0); @@ -599,6 +595,8 @@ void Init_ssl(VALUE mSSL) rb_attr(cSSLSocket, rb_intern(ssl_attr_readers[i]), 1, 0, Qfalse); rb_define_alias(cSSLSocket, "to_io", "io"); +#define ssl_def_const(x) rb_define_const(module, #x, INT2FIX(SSL_##x)) + ssl_def_const(VERIFY_NONE); ssl_def_const(VERIFY_PEER); ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT); diff --git a/ossl_version.h b/ossl_version.h index a4c0763..b7b9491 100644 --- a/ossl_version.h +++ b/ossl_version.h @@ -2,7 +2,7 @@ #define OSSL_VERSION_H /*#define OSSL_VERSION "0.0.10"*/ -#define OSSL_VERSION "CVS $Revision$ ($Date$)" +#define OSSL_VERSION "CVS SNAPSHOT ($Date$)" #endif diff --git a/ossl_x509.c b/ossl_x509.c index 85e6b33..e9009f9 100644 --- a/ossl_x509.c +++ b/ossl_x509.c @@ -87,8 +87,10 @@ ossl_x509_new_from_file(VALUE filename) VALUE obj; MakeX509(obj, x509p); - + + Check_SafeStr(filename); path = RSTRING(filename)->ptr; + if ((fp = fopen(path, "r")) == NULL) rb_raise(eX509CertificateError, "%s", strerror(errno)); @@ -97,6 +99,7 @@ ossl_x509_new_from_file(VALUE filename) if (!cert) rb_raise(eX509CertificateError, "%s", ossl_error()); + x509p->x509 = cert; return obj; @@ -108,13 +111,11 @@ ossl_x509_get_X509(VALUE obj) ossl_x509 *x509p = NULL; X509 *x509 = NULL; - OSSL_Check_Type(obj, cX509Certificate); - + OSSL_Check_Type(obj, cX509Certificate); GetX509(obj, x509p); - if (!(x509 = X509_dup(x509p->x509))) { + if (!(x509 = X509_dup(x509p->x509))) rb_raise(eX509CertificateError, "%s", ossl_error()); - } return x509; } @@ -151,13 +152,16 @@ ossl_x509_initialize(int argc, VALUE *argv, VALUE self) case T_NIL: x509 = X509_new(); break; + case T_STRING: - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, -1))) { + Check_SafeStr(buffer); + if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) { rb_raise(eX509CertificateError, "%s", ossl_error()); } x509 = PEM_read_bio_X509(in, NULL, NULL, NULL); BIO_free(in); break; + default: rb_raise(rb_eTypeError, "unsupported type"); } @@ -301,7 +305,7 @@ ossl_x509_get_serial(VALUE self) GetX509(self, x509p); - if (!(asn1int = X509_get_serialNumber(x509p->x509))) { + if (!(asn1int = X509_get_serialNumber(x509p->x509))) { /* NO DUP - don't free */ rb_raise(eX509CertificateError, "%s", ossl_error()); } serial = ASN1_INTEGER_get(asn1int); @@ -324,7 +328,7 @@ ossl_x509_set_serial(VALUE self, VALUE serial) ASN1_INTEGER_free(asn1int); rb_raise(eX509CertificateError, "%s", ossl_error()); } - if (!X509_set_serialNumber(x509p->x509, asn1int)) { + if (!X509_set_serialNumber(x509p->x509, asn1int)) { /* DUPs asn1int - FREE it */ ASN1_INTEGER_free(asn1int); rb_raise(eX509CertificateError, "%s", ossl_error()); } @@ -341,7 +345,7 @@ ossl_x509_get_subject(VALUE self) GetX509(self, x509p); - if (!(name = X509_get_subject_name(x509p->x509))) { + if (!(name = X509_get_subject_name(x509p->x509))) { /* NO DUP - don't free! */ rb_raise(eX509CertificateError, "%s", ossl_error()); } @@ -359,9 +363,11 @@ ossl_x509_set_subject(VALUE self, VALUE subject) OSSL_Check_Type(subject, cX509Name); name = ossl_x509name_get_X509_NAME(subject); - if (!X509_set_subject_name(x509p->x509, name)) { + if (!X509_set_subject_name(x509p->x509, name)) { /* DUPs name - FREE it */ + X509_NAME_free(name); rb_raise(eX509CertificateError, "%s", ossl_error()); } + X509_NAME_free(name); return subject; } @@ -371,11 +377,10 @@ ossl_x509_get_issuer(VALUE self) { ossl_x509 *x509p = NULL; X509_NAME *name = NULL; - VALUE issuer; GetX509(self, x509p); - if(!(name = X509_get_issuer_name(x509p->x509))) { + if(!(name = X509_get_issuer_name(x509p->x509))) { /* NO DUP - don't free! */ rb_raise(eX509CertificateError, "%s", ossl_error()); } @@ -393,7 +398,8 @@ ossl_x509_set_issuer(VALUE self, VALUE issuer) OSSL_Check_Type(issuer, cX509Name); name = ossl_x509name_get_X509_NAME(issuer); - if (!X509_set_issuer_name(x509p->x509, name)) { + if (!X509_set_issuer_name(x509p->x509, name)) { /* DUPs name - FREE it */ + X509_NAME_free(name); rb_raise(eX509CertificateError, "%s", ossl_error()); } X509_NAME_free(name); @@ -409,7 +415,7 @@ ossl_x509_get_not_before(VALUE self) GetX509(self, x509p); - if (!(asn1time = X509_get_notBefore(x509p->x509))) { + if (!(asn1time = X509_get_notBefore(x509p->x509))) { /* NO DUP - don't free! */ rb_raise(eX509CertificateError, "%s", ossl_error()); } @@ -448,7 +454,7 @@ ossl_x509_get_not_after(VALUE self) GetX509(self, x509p); - if (!(asn1time = X509_get_notAfter(x509p->x509))) { + if (!(asn1time = X509_get_notAfter(x509p->x509))) { /* NO DUP - don't free! */ rb_raise(eX509CertificateError, "%s", ossl_error()); } @@ -488,7 +494,7 @@ ossl_x509_get_public_key(VALUE self) GetX509(self, x509p); - if (!(pkey = X509_get_pubkey(x509p->x509))) { + if (!(pkey = X509_get_pubkey(x509p->x509))) { /* adds an reference - safe to FREE */ rb_raise(eX509CertificateError, "%s", ossl_error()); } pub_key = ossl_pkey_new(pkey); @@ -508,7 +514,7 @@ ossl_x509_set_public_key(VALUE self, VALUE pubk) pkey = ossl_pkey_get_EVP_PKEY(pubk); - if (!X509_set_pubkey(x509p->x509, pkey)) { + if (!X509_set_pubkey(x509p->x509, pkey)) { /* DUPs pkey - FREE it */ EVP_PKEY_free(pkey); rb_raise(eX509CertificateError, "%s", ossl_error()); } @@ -529,7 +535,7 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest) OSSL_Check_Type(digest, cDigest); if (rb_funcall(key, rb_intern("private?"), 0, NULL) == Qfalse) { - rb_raise(eX509CertificateError, "PRIVATE key needed to sign REQ!"); + rb_raise(eX509CertificateError, "PRIVATE key needed to sign X509 Certificate!"); } pkey = ossl_pkey_get_EVP_PKEY(key); @@ -615,7 +621,7 @@ ossl_x509_get_extensions(VALUE self) return rb_ary_new(); for (i=0; i<count; i++) { - ext = X509_get_ext(x509p->x509, i); + ext = X509_get_ext(x509p->x509, i); /* NO DUP - don't free! */ rb_ary_push(ary, ossl_x509ext_new(ext)); } @@ -631,41 +637,48 @@ ossl_x509_set_extensions(VALUE self, VALUE ary) ossl_x509 *x509p = NULL; X509_EXTENSION *ext = NULL; int i = 0; - VALUE item; GetX509(self, x509p); Check_Type(ary, T_ARRAY); + for (i=0; i<RARRAY(ary)->len; i++) { /* All ary's members should be X509Extension */ + OSSL_Check_Type(RARRAY(ary)->ptr[i], cX509Extension); + } sk_X509_EXTENSION_pop_free(x509p->x509->cert_info->extensions, X509_EXTENSION_free); x509p->x509->cert_info->extensions = NULL; for (i=0; i<RARRAY(ary)->len; i++) { - item = RARRAY(ary)->ptr[i]; - OSSL_Check_Type(item, cX509Extension); - ext = ossl_x509ext_get_X509_EXTENSION(item); - if (!X509_add_ext(x509p->x509, ext, -1)) { + ext = ossl_x509ext_get_X509_EXTENSION(RARRAY(ary)->ptr[i]); + + if (!X509_add_ext(x509p->x509, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); rb_raise(eX509CertificateError, "%s", ossl_error()); } + X509_EXTENSION_free(ext); } return ary; } static VALUE -ossl_x509_add_extension(VALUE self, VALUE ext) +ossl_x509_add_extension(VALUE self, VALUE extension) { ossl_x509 *x509p = NULL; - + X509_EXTENSION *ext = NULL; + GetX509(self, x509p); - OSSL_Check_Type(ext, cX509Extension); + OSSL_Check_Type(extension, cX509Extension); + ext = ossl_x509ext_get_X509_EXTENSION(extension); - if (!X509_add_ext(x509p->x509, ossl_x509ext_get_X509_EXTENSION(ext), -1)) { + if (!X509_add_ext(x509p->x509, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); rb_raise(eX509CertificateError, "%s", ossl_error()); } + X509_EXTENSION_free(ext); - return ext; + return extension; } /* diff --git a/ossl_x509attr.c b/ossl_x509attr.c index a80b4ad..ba98045 100644 --- a/ossl_x509attr.c +++ b/ossl_x509attr.c @@ -13,9 +13,9 @@ #define MakeX509Attr(obj, attrp) {\ obj = Data_Make_Struct(cX509Attribute, ossl_x509attr, 0, ossl_x509attr_free, attrp);\ } -#define GetX509Attr_unsafe(obj, attrp) Data_Get_Struct(obj, ossl_x509attr, attrp); + #define GetX509Attr(obj, attrp) {\ - GetX509Attr_unsafe(obj, attrp);\ + Data_Get_Struct(obj, ossl_x509attr, attrp);\ if (!attrp->attribute) rb_raise(eX509AttributeError, "not initialized!");\ } @@ -55,7 +55,7 @@ ossl_x509attr_new_null(void) MakeX509Attr(obj, attrp); if (!(attrp->attribute = X509_ATTRIBUTE_new())) - rb_raise(eX509AttributeError, "%s", ossl_error()); + OSSL_Raise(eX509AttributeError, ""); return obj; } @@ -71,9 +71,8 @@ ossl_x509attr_new(X509_ATTRIBUTE *attr) MakeX509Attr(obj, attrp); - if (!(attrp->attribute = X509_ATTRIBUTE_dup(attr))) { - rb_raise(eX509AttributeError, "%s", ossl_error()); - } + if (!(attrp->attribute = X509_ATTRIBUTE_dup(attr))) + OSSL_Raise(eX509AttributeError, ""); return obj; } @@ -84,12 +83,11 @@ ossl_x509attr_get_X509_ATTRIBUTE(VALUE obj) ossl_x509attr *attrp = NULL; X509_ATTRIBUTE *attr = NULL; - OSSL_Check_Type(obj, cX509Attribute); - + OSSL_Check_Type(obj, cX509Attribute); GetX509Attr(obj, attrp); if (!(attr = X509_ATTRIBUTE_dup(attrp->attribute))) - rb_raise(eX509AttributeError, "%s", ossl_error()); + OSSL_Raise(eX509AttributeError, ""); return attr; } @@ -98,24 +96,12 @@ ossl_x509attr_get_X509_ATTRIBUTE(VALUE obj) * private */ static VALUE -ossl_x509attr_s_new(int argc, VALUE *argv, VALUE klass) +ossl_x509attr_s_new_from_array(VALUE klass, VALUE ary) { ossl_x509attr *attrp = NULL; - VALUE obj; - - MakeX509Attr(obj, attrp); - - rb_obj_call_init(obj, argc, argv); - - return obj; -} - -X509_ATTRIBUTE * -ary_to_x509attr(VALUE ary) -{ X509_ATTRIBUTE *attr = NULL; int nid = NID_undef; - VALUE item; + VALUE item, obj; Check_Type(ary, T_ARRAY); @@ -125,55 +111,61 @@ ary_to_x509attr(VALUE ary) /* key [0] */ item = RARRAY(ary)->ptr[0]; - Check_Type(item, T_STRING); + Check_SafeStr(item); if (!(nid = OBJ_ln2nid(RSTRING(item)->ptr))) if (!(nid = OBJ_sn2nid(RSTRING(item)->ptr))) - rb_raise(eX509AttributeError, "%s", ossl_error()); + OSSL_Raise(eX509AttributeError, ""); /* data [1] */ item = RARRAY(ary)->ptr[1]; - Check_Type(item, T_STRING); + Check_SafeStr(item); - if (!(attr = X509_ATTRIBUTE_create(nid, MBSTRING_ASC, RSTRING(item)->ptr))) { - rb_raise(eX509AttributeError, "%s", ossl_error()); - } + if (!(attr = X509_ATTRIBUTE_create(nid, MBSTRING_ASC, RSTRING(item)->ptr))) + OSSL_Raise(eX509AttributeError, ""); - return attr; + MakeX509Attr(obj, attrp); + attrp->attribute = attr; + + return obj; } -static VALUE -ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self) +/* + * is there any print for attribute? + * (NO, but check t_req.c in crypto/asn1) + * +static VALUE +ossl_x509attr_to_a(VALUE self) { ossl_x509attr *attrp = NULL; - X509_ATTRIBUTE *attr = NULL; - VALUE arg1, arg2, ary; - - GetX509Attr_unsafe(self, attrp); + BIO *out = NULL; + BUF_MEM *buf = NULL; + int nid = NID_undef; + VALUE ary, value; - switch (rb_scan_args(argc, argv, "02", &arg1, &arg2)) { - case 0: - attr = X509_ATTRIBUTE_new(); - break; - case 1: - Check_Type(arg1, T_ARRAY); - attr = ary_to_x509attr(ary); - break; - case 2: - ary = rb_ary_new2(2); - rb_ary_push(ary, arg1); - rb_ary_push(ary, arg2); - attr = ary_to_x509attr(ary); - break; - default: - rb_raise(rb_eTypeError, "unsupported type"); - } - if (!attr) - rb_raise(eX509AttributeError, "%s", ossl_error()); + GetX509Attr(obj, attrp); - attrp->attribute = attr; + ary = rb_ary_new2(2); + + nid = OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attrp->attribute)); + rb_ary_push(ary, rb_str_new2(OBJ_nid2sn(nid))); - return self; + if (!(out = BIO_new(BIO_s_mem()))) + OSSL_Raise(eX509ExtensionError, ""); + + if (!X509V3_???_print(out, extp->extension, 0, 0)) { + BIO_free(out); + OSSL_Raise(eX509ExtensionError, ""); + } + BIO_get_mem_ptr(out, &buf); + value = rb_str_new(buf->data, buf->length); + BIO_free(out); + + rb_funcall(value, rb_intern("tr!"), 2, rb_str_new2("\n"), rb_str_new2(",")); + rb_ary_push(ary, value); + + return ary; } + */ /* * X509_ATTRIBUTE init @@ -184,11 +176,9 @@ Init_ossl_x509attr(VALUE module) eX509AttributeError = rb_define_class_under(module, "AttributeError", rb_eStandardError); cX509Attribute = rb_define_class_under(module, "Attribute", rb_cObject); - rb_define_singleton_method(cX509Attribute, "new", ossl_x509attr_s_new, -1); - rb_define_method(cX509Attribute, "initialize", ossl_x509attr_initialize, -1); + rb_define_singleton_method(cX509Attribute, "new_from_array", ossl_x509attr_s_new_from_array, 1); /* * TODO: - rb_define_method(cX509Attribute, "to_str", ossl_x509attr_to_str, 0); rb_define_method(cX509Attribute, "to_a", ossl_x509attr_to_a, 0); */ } diff --git a/ossl_x509crl.c b/ossl_x509crl.c index 4025b1c..ba4e430 100644 --- a/ossl_x509crl.c +++ b/ossl_x509crl.c @@ -95,6 +95,7 @@ ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self) crl = X509_CRL_new(); break; case T_STRING: + Check_SafeStr(buffer); if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, -1))) { rb_raise(eX509CRLError, "%s", ossl_error()); } @@ -150,7 +151,6 @@ static VALUE ossl_x509crl_get_issuer(VALUE self) { ossl_x509crl *crlp = NULL; - X509_NAME *name = NULL; GetX509CRL(self, crlp); @@ -168,7 +168,8 @@ ossl_x509crl_set_issuer(VALUE self, VALUE issuer) OSSL_Check_Type(issuer, cX509Name); name = ossl_x509name_get_X509_NAME(issuer); - if (!X509_NAME_set(&(crlp->crl->crl->issuer), name)) { + if (!X509_NAME_set(&(crlp->crl->crl->issuer), name)) { /* DUPs name - FREE it */ + X509_NAME_free(name); rb_raise(eX509CRLError, "%s", ossl_error()); } X509_NAME_free(name); @@ -243,7 +244,8 @@ ossl_x509crl_get_revoked(VALUE self) { ossl_x509crl *crlp = NULL; int i, num = 0; - VALUE ary; + X509_REVOKED *rev = NULL; + VALUE ary, revoked; GetX509CRL(self, crlp); @@ -255,7 +257,9 @@ ossl_x509crl_get_revoked(VALUE self) ary = rb_ary_new2(num); for(i=0; i<num; i++) { - rb_ary_push(ary, ossl_x509revoked_new((X509_REVOKED *)sk_X509_CRL_value(crlp->crl->crl->revoked, i))); + rev = (X509_REVOKED *)sk_X509_CRL_value(crlp->crl->crl->revoked, i); /* NO DUP - don't free! */ + revoked = ossl_x509revoked_new(rev); + rb_ary_push(ary, revoked); } return ary; @@ -267,22 +271,22 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary) ossl_x509crl *crlp = NULL; X509_REVOKED *rev = NULL; int i; - VALUE item; GetX509CRL(self, crlp); Check_Type(ary, T_ARRAY); - + for (i=0; i<RARRAY(ary)->len; i++) { /* All ary members should be X509 Revoked */ + OSSL_Check_Type(RARRAY(ary)->ptr[i], cX509Revoked); + } + sk_X509_REVOKED_pop_free(crlp->crl->crl->revoked, X509_REVOKED_free); crlp->crl->crl->revoked = NULL; M_ASN1_New(crlp->crl->crl->revoked, sk_X509_REVOKED_new_null); for (i=0; i<RARRAY(ary)->len; i++) { - item = RARRAY(ary)->ptr[i]; - OSSL_Check_Type(item, cX509Revoked); - rev = ossl_x509revoked_get_X509_REVOKED(item); + rev = ossl_x509revoked_get_X509_REVOKED(RARRAY(ary)->ptr[i]); - if (!sk_X509_CRL_push(crlp->crl->crl->revoked, rev)) { + if (!sk_X509_CRL_push(crlp->crl->crl->revoked, rev)) { /* NO DUP - don't free! */ rb_raise(eX509CRLError, "%s", ossl_error()); } } @@ -302,7 +306,7 @@ ossl_x509crl_add_revoked(VALUE self, VALUE revoked) OSSL_Check_Type(revoked, cX509Revoked); rev = ossl_x509revoked_get_X509_REVOKED(revoked); - if (!sk_X509_CRL_push(crlp->crl->crl->revoked, rev)) { + if (!sk_X509_CRL_push(crlp->crl->crl->revoked, rev)) { /* NO DUP - don't free! */ rb_raise(eX509CRLError, "%s", ossl_error()); } sk_X509_REVOKED_sort(crlp->crl->crl->revoked); @@ -348,7 +352,6 @@ ossl_x509crl_verify(VALUE self, VALUE key) GetX509CRL(self, crlp); OSSL_Check_Type(key, cPKey); - pkey = ossl_pkey_get_EVP_PKEY(key); result = X509_CRL_verify(crlp->crl, pkey); @@ -405,6 +408,7 @@ ossl_x509crl_to_str(VALUE self) return str; } + /* * Gets X509v3 extensions as array of X509Ext objects */ @@ -426,7 +430,7 @@ ossl_x509crl_get_extensions(VALUE self) return rb_ary_new(); for (i=0; i<count; i++) { - ext = X509_CRL_get_ext(crlp->crl, i); + ext = X509_CRL_get_ext(crlp->crl, i); /* NO DUP - don't free! */ rb_ary_push(ary, ossl_x509ext_new(ext)); } @@ -442,41 +446,48 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary) ossl_x509crl *crlp = NULL; X509_EXTENSION *ext = NULL; int i = 0; - VALUE item; GetX509CRL(self, crlp); Check_Type(ary, T_ARRAY); + for (i=0; i<RARRAY(ary)->len; i++) { /* All ary members should be X509 Extensions */ + OSSL_Check_Type(RARRAY(ary)->ptr[i], cX509Extension); + } sk_X509_EXTENSION_pop_free(crlp->crl->crl->extensions, X509_EXTENSION_free); crlp->crl->crl->extensions = NULL; for (i=0; i<RARRAY(ary)->len; i++) { - item = RARRAY(ary)->ptr[i]; - OSSL_Check_Type(item, cX509Extension); - ext = ossl_x509ext_get_X509_EXTENSION(item); - if(!X509_CRL_add_ext(crlp->crl, ext, -1)) { + ext = ossl_x509ext_get_X509_EXTENSION(RARRAY(ary)->ptr[i]); + + if(!X509_CRL_add_ext(crlp->crl, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); rb_raise(eX509CRLError, "%s", ossl_error()); } + X509_EXTENSION_free(ext); } return ary; } static VALUE -ossl_x509crl_add_extension(VALUE self, VALUE ext) +ossl_x509crl_add_extension(VALUE self, VALUE extension) { ossl_x509crl *crlp = NULL; + X509_EXTENSION *ext = NULL; GetX509CRL(self, crlp); - OSSL_Check_Type(ext, cX509Extension); - - if(!X509_CRL_add_ext(crlp->crl, ossl_x509ext_get_X509_EXTENSION(ext), -1)) { + OSSL_Check_Type(extension, cX509Extension); + ext = ossl_x509ext_get_X509_EXTENSION(extension); + + if(!X509_CRL_add_ext(crlp->crl, ext, -1)) { /* DUPs ext - FREE it */ + X509_EXTENSION_free(ext); rb_raise(eX509CRLError, "%s", ossl_error()); } + X509_EXTENSION_free(ext); - return ext; + return extension; } /* diff --git a/ossl_x509ext.c b/ossl_x509ext.c index 644697e..2a5bf33 100644 --- a/ossl_x509ext.c +++ b/ossl_x509ext.c @@ -13,18 +13,16 @@ #define MakeX509Ext(obj, extp) {\ obj = Data_Make_Struct(cX509Extension, ossl_x509ext, 0, ossl_x509ext_free, extp);\ } -#define GetX509Ext_unsafe(obj, extp) Data_Get_Struct(obj, ossl_x509ext, extp) #define GetX509Ext(obj, extp) {\ - GetX509Ext_unsafe(obj, extp);\ + Data_Get_Struct(obj, ossl_x509ext, extp);\ if (!extp->extension) rb_raise(eX509ExtensionError, "not initialized!");\ } #define MakeX509ExtFactory(obj, extfactoryp) {\ obj = Data_Make_Struct(cX509ExtensionFactory, ossl_x509extfactory, 0, ossl_x509extfactory_free, extfactoryp);\ } -#define GetX509ExtFactory(obj, extfactoryp) {\ - Data_Get_Struct(obj, ossl_x509extfactory, extfactoryp);\ -} +#define GetX509ExtFactory(obj, extfactoryp) \ + Data_Get_Struct(obj, ossl_x509extfactory, extfactoryp) /* * Classes @@ -102,8 +100,7 @@ ossl_x509ext_get_X509_EXTENSION(VALUE obj) { ossl_x509ext *extp = NULL; - OSSL_Check_Type(obj, cX509Extension); - + OSSL_Check_Type(obj, cX509Extension); GetX509Ext(obj, extp); return X509_EXTENSION_dup(extp->extension); @@ -207,20 +204,6 @@ ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) } /* -X509_NAME *str_to_x509ext(VALUE str) -{ - X509_NAME *name = NULL; - - rb_raise(eX509ExtensionError, "TODO!"); - - Check_Type(str, T_STRING); - if (!(name = X509_NAME_new())) { - rb_raise(eX509ExtensionError, "%s", ossl_error()); - } -} - */ - -/* * Array to X509_EXTENSION * Structure: * ["ln", "value", bool_critical] or @@ -228,14 +211,18 @@ X509_NAME *str_to_x509ext(VALUE str) * ["ln", "critical,value"] or the same for sn * ["ln", "value"] => not critical */ -X509_EXTENSION * -ary_to_x509ext(VALUE ary, X509V3_CTX *ctx) +static VALUE +ossl_x509extfactory_create_ext_from_array(VALUE self, VALUE ary) { + ossl_x509extfactory *extfactoryp = NULL; + ossl_x509ext *extp = NULL; X509_EXTENSION *ext = NULL; int nid = NID_undef; char *value = NULL; - VALUE item; - + VALUE item,obj; + + GetX509ExtFactory(self, extfactoryp); + Check_Type(ary, T_ARRAY); if ((RARRAY(ary)->len) < 2 || (RARRAY(ary)->len > 3)) { /*2 or 3 allowed*/ @@ -244,19 +231,21 @@ ary_to_x509ext(VALUE ary, X509V3_CTX *ctx) if (!(ext = X509_EXTENSION_new())) { rb_raise(eX509ExtensionError, "%s", ossl_error()); } + /* key [0] */ item = RARRAY(ary)->ptr[0]; - Check_Type(item, T_STRING); + Check_SafeStr(item); if (!(nid = OBJ_ln2nid(RSTRING(item)->ptr))) if (!(nid = OBJ_sn2nid(RSTRING(item)->ptr))) rb_raise(eX509ExtensionError, "%s", ossl_error()); + /* data [1] */ item = RARRAY(ary)->ptr[1]; - Check_Type(item, T_STRING); + Check_SafeStr(item); /* (optional) critical [2] */ if (RARRAY(ary)->len == 3 && RARRAY(ary)->ptr[2] == Qtrue) { - if (!(value = malloc((RSTRING(item)->len)+strlen("critical,")+1))) { + if (!(value = malloc(strlen("critical,")+(RSTRING(item)->len)+1))) { rb_raise(eX509ExtensionError, "malloc error"); } strcpy(value, "critical,"); @@ -264,54 +253,12 @@ ary_to_x509ext(VALUE ary, X509V3_CTX *ctx) } else value = strdup(RSTRING(item)->ptr); - if (!(ext = X509V3_EXT_conf_nid(NULL, ctx, nid, value))) { + if (!(ext = X509V3_EXT_conf_nid(NULL, &(extfactoryp->ctx), nid, value))) { free(value); rb_raise(eX509ExtensionError, "%s", ossl_error()); } free(value); - return ext; -} - -static VALUE -ossl_x509extfactory_create_extension(int argc, VALUE *argv, VALUE self) -{ - ossl_x509extfactory *extfactoryp = NULL; - ossl_x509ext *extp = NULL; - X509_EXTENSION *ext = NULL; - VALUE obj,ary,arg1,arg2,arg3; - - GetX509ExtFactory(self, extfactoryp); - - switch (rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3)) { - case 1: - ary = arg1; - break; - case 2: - arg3 = Qnil; - case 3: - ary = rb_ary_new2(3); - rb_ary_push(ary, arg1); - rb_ary_push(ary, arg2); - rb_ary_push(ary, arg3); - break; - default: - rb_raise(rb_eTypeError, "unsupported type"); - } - - switch (TYPE(ary)) { - /* - case T_STRING: - ext = str_to_x509ext(ary); - break; - */ - case T_ARRAY: - ext = ary_to_x509ext(ary, &(extfactoryp->ctx)); - break; - default: - rb_raise(rb_eTypeError, "unsupported type"); - } - MakeX509Ext(obj, extp); extp->extension = ext; @@ -322,43 +269,6 @@ ossl_x509extfactory_create_extension(int argc, VALUE *argv, VALUE self) * Extension */ static VALUE -ossl_x509ext_to_str(VALUE obj) -{ - ossl_x509ext *extp = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; - int nid = NID_undef, critical; - VALUE str; - - GetX509Ext(obj, extp); - - if (!(out = BIO_new(BIO_s_mem()))) { - rb_raise(eX509ExtensionError, "%s", ossl_error()); - } - - /* - * TODO: - * User defined user format - */ - nid = OBJ_obj2nid(X509_EXTENSION_get_object(extp->extension)); - - BIO_printf(out, "OID=%s, VALUE=", (nid == NID_undef)?"UNKNOWN":OBJ_nid2sn(nid)); /*OBJ_nid2ln(nid)*/ - - if (!X509V3_EXT_print(out, extp->extension, 0, 0)) { - BIO_free(out); - rb_raise(eX509ExtensionError, "%s", ossl_error()); - } - critical = X509_EXTENSION_get_critical(extp->extension); - BIO_printf(out,", critical = %s\n", (critical)?"yes":"no"); - - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); - - return str; -} - -static VALUE ossl_x509ext_to_a(VALUE obj) { ossl_x509ext *extp = NULL; @@ -372,7 +282,7 @@ ossl_x509ext_to_a(VALUE obj) ary = rb_ary_new2(3); nid = OBJ_obj2nid(X509_EXTENSION_get_object(extp->extension)); - rb_ary_push(ary, rb_str_new2((nid == NID_undef)?"UNKNOWN":OBJ_nid2sn(nid))); + rb_ary_push(ary, rb_str_new2(OBJ_nid2sn(nid))); if (!(out = BIO_new(BIO_s_mem()))) { rb_raise(eX509ExtensionError, "%s", ossl_error()); @@ -389,7 +299,7 @@ ossl_x509ext_to_a(VALUE obj) rb_ary_push(ary, value); critical = X509_EXTENSION_get_critical(extp->extension); - rb_ary_push(ary, (critical)?Qtrue:Qfalse); + rb_ary_push(ary, (critical) ? Qtrue : Qfalse); return ary; } @@ -410,7 +320,7 @@ Init_ossl_x509ext(VALUE module) rb_define_method(cX509ExtensionFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1); rb_define_method(cX509ExtensionFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); rb_define_method(cX509ExtensionFactory, "crl=", ossl_x509extfactory_set_crl, 1); - rb_define_method(cX509ExtensionFactory, "create_extension", ossl_x509extfactory_create_extension, -1); + rb_define_method(cX509ExtensionFactory, "create_ext_from_array", ossl_x509extfactory_create_ext_from_array, 1); cX509Extension = rb_define_class_under(module, "Extension", rb_cObject); rb_undef_method(CLASS_OF(cX509Extension), "new"); @@ -418,7 +328,6 @@ Init_ossl_x509ext(VALUE module) rb_define_singleton_method(cX509Extension, "new", ossl_x509ext_s_new, -1); rb_define_method(cX509Extension, "initialize", ossl_x509ext_initialize, -1); */ - rb_define_method(cX509Extension, "to_str", ossl_x509ext_to_str, 0); rb_define_method(cX509Extension, "to_a", ossl_x509ext_to_a, 0); } diff --git a/ossl_x509name.c b/ossl_x509name.c index 452faf9..2fa5665 100644 --- a/ossl_x509name.c +++ b/ossl_x509name.c @@ -9,13 +9,13 @@ * (See the file 'LICENCE'.) */ #include "ossl.h" +#include "st.h" /* For st_foreach -- ST_CONTINUE */ #define MakeX509Name(obj, namep) {\ obj = Data_Make_Struct(cX509Name, ossl_x509name, 0, ossl_x509name_free, namep);\ } -#define GetX509Name_unsafe(obj, namep) Data_Get_Struct(obj, ossl_x509name, namep) #define GetX509Name(obj, namep) {\ - GetX509Name_unsafe(obj, namep);\ + Data_Get_Struct(obj, ossl_x509name, namep);\ if (!namep->name) rb_raise(eX509NameError, "not initialized!");\ } @@ -55,7 +55,7 @@ ossl_x509name_new_null(void) MakeX509Name(obj, namep); if (!(namep->name = X509_NAME_new())) - rb_raise(eX509NameError, "%s", ossl_error()); + OSSL_Raise(eX509NameError, ""); return obj; } @@ -72,7 +72,7 @@ ossl_x509name_new(X509_NAME *name) MakeX509Name(obj, namep); if (!(namep->name = X509_NAME_dup(name))) - rb_raise(eX509NameError, "%s", ossl_error()); + OSSL_Raise(eX509NameError, ""); return obj; } @@ -82,8 +82,7 @@ ossl_x509name_get_X509_NAME(VALUE obj) { ossl_x509name *namep = NULL; - OSSL_Check_Type(obj, cX509Name); - + OSSL_Check_Type(obj, cX509Name); GetX509Name(obj, namep); return X509_NAME_dup(namep->name); @@ -92,190 +91,51 @@ ossl_x509name_get_X509_NAME(VALUE obj) /* * Private */ -static VALUE -ossl_x509name_s_new(int argc, VALUE *argv, VALUE klass) +/* + * Iterator for ossl_x509name_new_from_hash + */ +static int +ossl_x509name_hash_i(VALUE key, VALUE value, X509_NAME *name) { - ossl_x509name *namep = NULL; - VALUE obj; + int id, type; - MakeX509Name(obj, namep); - - rb_obj_call_init(obj, argc, argv); + Check_SafeStr(key); + Check_SafeStr(value); - return obj; -} - -static X509_NAME * -str_to_x509name(VALUE str) -{ - X509_NAME *name = NULL; - - /* - * TODO: - */ - rb_raise(eX509NameError, "TODO!"); - - Check_Type(str, T_STRING); - if (!(name = X509_NAME_new())) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - - return name; -} - -static X509_NAME * -ary_to_x509name(VALUE ary) -{ - X509_NAME *name = NULL; - long i,j; - int id, type; - VALUE item, key, value; - - Check_Type(ary, T_ARRAY); - - if (!(name = X509_NAME_new())) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - for (i=0; i<RARRAY(ary)->len; i++) { - item = RARRAY(ary)->ptr[i]; - if (TYPE(item) != T_ARRAY || RARRAY(item)->len != 2) { - rb_raise(eX509NameError, "unsupported structure"); + if (!(id = OBJ_ln2nid(RSTRING(key)->ptr))) + if (!(id = OBJ_sn2nid(RSTRING(key)->ptr))) { + X509_NAME_free(name); + OSSL_Raise(eX509NameError, "OBJ_...2nid:"); } - key = RARRAY(item)->ptr[0]; - value = RARRAY(item)->ptr[1]; - - if (TYPE(key) != T_STRING || TYPE(value) != T_STRING) { - rb_raise(eX509NameError, "unsupported structure"); - } - if (!(id = OBJ_ln2nid(RSTRING(key)->ptr))) - if (!(id = OBJ_sn2nid(RSTRING(key)->ptr))) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - type = ASN1_PRINTABLE_type(RSTRING(value)->ptr, -1); + + type = ASN1_PRINTABLE_type(RSTRING(value)->ptr, -1); - if (!X509_NAME_add_entry_by_NID(name, id, type, RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) { - rb_raise(eX509NameError, "%s", ossl_error()); - } + if (!X509_NAME_add_entry_by_NID(name, id, type, RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) { + X509_NAME_free(name); + OSSL_Raise(eX509NameError, ""); } - return name; -} -/* -static X509_NAME * -hash_to_x509name(VALUE ary) -{ - X509_NAME *name = NULL; - long i,j; - int id, type; - VALUE item, key, value; - - Check_Type(ary, T_HASH); - - if (!(name = X509_NAME_new())) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - for (i=0; i<RARRAY(ary)->len; i++) { - item = RARRAY(ary)->ptr[i]; - if (TYPE(item) != T_ARRAY || RARRAY(item)->len != 2) { - rb_raise(eX509NameError, "unsupported structure"); - } - key = RARRAY(item)->ptr[0]; - value = RARRAY(item)->ptr[1]; - if (TYPE(key) != T_STRING || TYPE(value) != T_STRING) { - rb_raise(eX509NameError, "unsupported structure"); - } - if (!(id = OBJ_ln2nid(RSTRING(key)->ptr))) - if (!(id = OBJ_sn2nid(RSTRING(key)->ptr))) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - type = ASN1_PRINTABLE_type(RSTRING(value)->ptr, -1); - - if (!X509_NAME_add_entry_by_NID(name, id, type, RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - } - return name; + return ST_CONTINUE; } -*/ static VALUE -ossl_x509name_initialize(int argc, VALUE *argv, VALUE self) +ossl_x509name_s_new_from_hash(VALUE klass, VALUE hash) { ossl_x509name *namep = NULL; X509_NAME *name = NULL; - VALUE arg; - - GetX509Name_unsafe(self, namep); + VALUE obj; - rb_scan_args(argc, argv, "01", &arg); + Check_Type(hash, T_HASH); - switch (TYPE(arg)) { - case T_NIL: - name = X509_NAME_new(); - break; - case T_STRING: - name = str_to_x509name(arg); - break; - case T_ARRAY: - name = ary_to_x509name(arg); - break; - default: - rb_raise(rb_eTypeError, "unsupported type"); - } - if (!name) - rb_raise(eX509NameError, "%s", ossl_error()); + if (!(name = X509_NAME_new())) + OSSL_Raise(eX509NameError, ""); - namep->name = name; - - return self; -} - -static VALUE -ossl_x509name_to_str(VALUE self) -{ - ossl_x509name *namep = NULL; - char *name = NULL; + st_foreach(RHASH(hash)->tbl, ossl_x509name_hash_i, name); - GetX509Name(self, namep); - - /* - * TODO: - * User defined user format - */ - name = X509_NAME_oneline(namep->name, NULL, 0); - - return rb_str_new2(name); -} - -static VALUE -ossl_x509name_to_a(VALUE self) -{ - ossl_x509name *namep = NULL; - X509_NAME_ENTRY *entry = NULL; - int i,entries = 0; - char *value=NULL, long_name[512]; - const char *short_name = NULL; - VALUE ary; + MakeX509Name(obj, namep); + namep->name = name; - GetX509Name(self, namep); - - entries = X509_NAME_entry_count(namep->name); - - ary = rb_ary_new2(entries); - - for (i=0; i<entries; i++) { - if (!(entry = X509_NAME_get_entry(namep->name, i))) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) { - rb_raise(eX509NameError, "%s", ossl_error()); - } - short_name = OBJ_nid2sn(OBJ_ln2nid(long_name)); - - rb_ary_push(ary, rb_assoc_new(rb_str_new2(short_name), rb_str_new(entry->value->data, entry->value->length))); - } - - return ary; + return obj; } static VALUE @@ -284,7 +144,7 @@ ossl_x509name_to_h(VALUE self) ossl_x509name *namep = NULL; X509_NAME_ENTRY *entry = NULL; int i,entries = 0; - char *value=NULL, long_name[512]; + char long_name[512]; const char *short_name = NULL; VALUE hash; @@ -296,10 +156,10 @@ ossl_x509name_to_h(VALUE self) for (i=0; i<entries; i++) { if (!(entry = X509_NAME_get_entry(namep->name, i))) { - rb_raise(eX509NameError, "%s", ossl_error()); + OSSL_Raise(eX509NameError, ""); } if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) { - rb_raise(eX509NameError, "%s", ossl_error()); + OSSL_Raise(eX509NameError, ""); } short_name = OBJ_nid2sn(OBJ_ln2nid(long_name)); @@ -318,10 +178,7 @@ Init_ossl_x509name(VALUE module) eX509NameError = rb_define_class_under(module, "NameError", rb_eStandardError); cX509Name = rb_define_class_under(module, "Name", rb_cObject); - rb_define_singleton_method(cX509Name, "new", ossl_x509name_s_new, -1); - rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1); - rb_define_method(cX509Name, "to_str", ossl_x509name_to_str, 0); - rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0); + rb_define_singleton_method(cX509Name, "new_from_hash", ossl_x509name_s_new_from_hash, 1); rb_define_method(cX509Name, "to_h", ossl_x509name_to_h, 0); } diff --git a/ossl_x509req.c b/ossl_x509req.c index 6f8c2fa..79bad9e 100644 --- a/ossl_x509req.c +++ b/ossl_x509req.c @@ -126,6 +126,7 @@ ossl_x509req_initialize(int argc, VALUE *argv, VALUE self) req = X509_REQ_new(); break; case T_STRING: + Check_SafeStr(buffer); if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, -1))) { rb_raise(eX509RequestError, "%s", ossl_error()); } @@ -428,8 +429,6 @@ static VALUE ossl_x509req_add_attribute(VALUE self, VALUE attr) { ossl_x509req *reqp = NULL; - int i = 0; - VALUE item; GetX509Req(self, reqp); diff --git a/ossl_x509revoked.c b/ossl_x509revoked.c index 441047a..de4f6cb 100644 --- a/ossl_x509revoked.c +++ b/ossl_x509revoked.c @@ -148,7 +148,6 @@ static VALUE ossl_x509revoked_get_time(VALUE obj) { ossl_x509revoked *revp = NULL; - ASN1_UTCTIME *asn1time = NULL; GetX509Revoked(obj, revp); diff --git a/ossl_x509store.c b/ossl_x509store.c index e6ac2e3..2b27104 100644 --- a/ossl_x509store.c +++ b/ossl_x509store.c @@ -84,7 +84,6 @@ ossl_x509store_get_X509_STORE(VALUE obj) ossl_x509store *storep = NULL; OSSL_Check_Type(obj, cX509Store); - GetX509Store(obj, storep); storep->protect = 1; /* we gave out internal pointer without DUP - don't free this one */ @@ -136,9 +135,9 @@ ossl_session_db_set(void *key, VALUE data) last = item; item = last->next; } - if (!(item = (ossl_session_db *)malloc(sizeof(ossl_session_db)))) { + if (!(item = (ossl_session_db *)OPENSSL_malloc(sizeof(ossl_session_db)))) { rb_thread_critical = 0; - rb_raise(ePKCS7Error, "MALLOC ERROR"); + OSSL_Raise(eX509StoreError, ""); } item->key = key; item->data = data; @@ -356,7 +355,7 @@ ossl_x509store_verify(VALUE self, VALUE cert) X509_STORE_CTX_set_cert(storep->store, x509); result = X509_verify_cert(storep->store); - /*X509_STORE_CTX_cleanup(storep->store); /*clears chain*/ + /*X509_STORE_CTX_cleanup(storep->store); *clears chain*/ if (result == 1) return Qtrue; return Qfalse; @@ -376,7 +375,6 @@ static VALUE ossl_x509store_get_verify_message(VALUE self) { ossl_x509store *storep = NULL; - VALUE messages; GetX509Store(self, storep); @@ -387,7 +385,6 @@ static VALUE ossl_x509store_get_verify_depth(VALUE self) { ossl_x509store *storep = NULL; - VALUE depth; GetX509Store(self, storep); @@ -398,7 +395,6 @@ static VALUE ossl_x509store_get_cert(VALUE self) { ossl_x509store *storep = NULL; - VALUE cert; GetX509Store(self, storep); @@ -437,7 +433,6 @@ ossl_x509store_load_locations(VALUE self, VALUE path) GetX509Store(self, storep); - Check_Type(path, T_STRING); Check_SafeStr(path); if (!X509_STORE_load_locations(storep->store->ctx, NULL, RSTRING(path)->ptr)) { diff --git a/test/ossl_x509.rb b/test/ossl_x509.rb index 4a7abe3..1c65217 100755 --- a/test/ossl_x509.rb +++ b/test/ossl_x509.rb @@ -38,6 +38,11 @@ p x509 = Certificate.new(File.open("./01cert.pem").read) p key = RSA.new(1024) p new = Certificate.new name = [['C', 'CZ'],['O','Rokos'],['CN','pokusXXX']] +#p n = Name.new(name) +#p n.to_h +#p n.to_a +#p n.to_str +#exit p new.subject = Name.new(name) p new.issuer = Name.new(name) p new.not_before = Time.now @@ -48,6 +53,10 @@ p new.version = 3 #p new.extensions #each_with_index {|e, i| p e.to_a} maker = ExtensionFactory.new(nil, new) #only subject p ext1 = maker.create_extension(["basicConstraints","CA:FALSE,pathlen:5"]) +#p ext1.to_a +#p ext1.to_h +#p ext1.to_str +#exit p ext2 = maker.create_extension(["nsComment","OK, man!!!"]) ###p digest = Digest::SHA1.new(new.public_key.to_der) ###p ext3 = maker.create_extension(["subjectKeyIdentifier", digest.hexdigest]) |