[or-cvs] r11214: some changes and new documentation (in topf/trunk: . config doc lib lib/fuzz-struct)
benedikt at seul.org
benedikt at seul.org
Mon Aug 20 11:09:05 UTC 2007
Author: benedikt
Date: 2007-08-20 07:09:04 -0400 (Mon, 20 Aug 2007)
New Revision: 11214
Added:
topf/trunk/binary/
Modified:
topf/trunk/config/config.yml
topf/trunk/doc/tutorial.tex
topf/trunk/lib/cell.rb
topf/trunk/lib/control.rb
topf/trunk/lib/dir.rb
topf/trunk/lib/fuzz-generic.rb
topf/trunk/lib/fuzz-struct/char-field.rb
topf/trunk/lib/fuzz-struct/float-field.rb
topf/trunk/lib/fuzz-struct/fuzz-struct.rb
topf/trunk/lib/fuzz-struct/hex-octet-field.rb
topf/trunk/lib/fuzz-struct/nested-field.rb
topf/trunk/lib/fuzz-struct/octet-field.rb
topf/trunk/lib/fuzz-struct/pad-field.rb
topf/trunk/lib/fuzz-struct/signed-field.rb
topf/trunk/lib/fuzz-struct/text-field.rb
topf/trunk/lib/fuzz-struct/unsigned-field.rb
topf/trunk/lib/fuzz-struct/yaml.rb
topf/trunk/lib/fuzz.rb
topf/trunk/lib/pkcs1.rb
topf/trunk/lib/topf.rb
topf/trunk/tor-control-fuzz.rb
topf/trunk/tor-dir-fuzz.rb
Log:
some changes and new documentation
Modified: topf/trunk/config/config.yml
===================================================================
--- topf/trunk/config/config.yml 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/config/config.yml 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,4 +1,3 @@
-
############################################################
# This file holds information about our running tor-service
############################################################
@@ -6,5 +5,8 @@
DIRPORT: "2324"
CONTROLPORT: "2323"
HOST: "127.0.0.1"
-KEYFILE: stuff/fuzz-private.pem
+KEYFILE: "stuff/fuzz-private.pem"
DEBUG: false
+COREDIR: "/home/Benedikt/topf/core"
+BINDIR: "/home/Benedikt/topf/binary"
+CONFDIR: "/home/Benedikt/topf/config"
Modified: topf/trunk/doc/tutorial.tex
===================================================================
--- topf/trunk/doc/tutorial.tex 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/doc/tutorial.tex 2007-08-20 11:09:04 UTC (rev 11214)
@@ -3,6 +3,7 @@
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
+
\author{Benedikt Boss}
\title{Howto use (T)he (O)nion (P)rotocol (F)uzzer}
\begin{document}
@@ -38,11 +39,53 @@
on your command-shell of choice.
\subsection{Running the fuzz tests}
+\subsubsection{Adjusting the config File}
+To let the Framework work properly the right setup of the
+config-file is nessesary. Just alter the given options
+to your environment.
-... steps to running the tests already in topf svn
+\begin{verbatim}
+DIRPORT: "2324"
+CONTROLPORT: "2323"
+HOST: "127.0.0.1"
+KEYFILE: "stuff/fuzz-private.pem"
+DEBUG: false
+COREDIR: "/home/your_user/topf/core"
+BINDIR: "/home/your_user/topf/binary"
+CONFDIR: "/home/your_user/topf/config"
+\end{verbatim}
-... and how to interpret the results
+\subsubsection{Setting the u-limit}
+To let your system create core-dumps you normaly have
+to adjust your ulimit. You can do this on the
+shell with the command: "ulimit -c unlimited"
+\subsubsection{Setting a core-pattern}
+T.O.P.F checks if a process has been crashed by diffing the
+coredump-directory that was setup in the config-file.
+To let your system create core-files in this directory you
+have to supply a core-pattern. If you work with Linux you
+can set the core-pattern with echoing a path+filepattern
+into the file in proc named core\_pattern.
+When using Fedora this can be done with the following command
+ executed as root:
+ \begin{verbatim}
+ echo "/home/youruser/path_to_topf/core/core" > /proc/sys/kernel/core_pattern
+ \end{verbatim}
+\subsubsection{Running the Dir-Port tests}
+To run the tests against the Dir-Port make sure you have setup
+the right host and dir-port in the configuration file.
+If everything is setup right you can just execute the dir-fuzzing
+with the command "ruby tor-dir-fuzz.rb".
+If something goes wrong a corefile should be dumped and the
+test-script should give you a backtrace and register information
+out of that corefile. Also it should print out the data that triggered
+the bug.
+\subsubsection{Running the Control-Port tests}
+Running tests against the Control-Port should be the same as running
+the tests against the Dir-Port. If you're sure you did all config options
+right you can execute "ruby tor-control-fuzz.rb" and the rest is done
+automatically.
\section{Writing T.O.P.F Structures}
As described in Section~\ref{working} (yeah? where? -RD), T.O.P.F
organizes its data in blocks. These blocks can have different types
@@ -53,8 +96,8 @@
#example1.rb
require "lib/fuzz-generic"
-class Example < BitStruct
- text :example, 7
+class Example < FuzzStruct
+ text :example, 7, :fuzzable => false
unsigned :version, 8
initial_value.example = "example"
@@ -67,13 +110,14 @@
pp e
end
\end{verbatim}
+This creates a Class called "Example" with the fields of a 8*8Bit long String,
+a 8Bit unsigned integer. and the initial values "example" and 1 for these.
+Also the Text-Field is declared as not fuzzable which means that later the
+value assigned to it remains the same. Next in the begin/end block the
+programm creates a Example object and sets the value of the version field to 2.
+This also demonstrates how you are able to access all fields after you created
+a fuzz-struct object.
-This creates a Class called "Example" with the fields of a 8*8Bit
-long String, a 8Bit unsigned integer. and the initial values "example"
-and 1 for these. Next in the begin/end block the programm creates a
-Example object and sets the value of the version field to 2. This also
-demonstrates how you are able to access all fields after you created a
-fuzz-struct object.
\subsection{Writing T.O.P.F Tests}
Tests in the Framework are organized on a field-type base. This means
@@ -85,16 +129,17 @@
\begin{verbatim}
a_test = Fuzz::Test.new("char") {|arg, size| "A"*1000}
\end{verbatim}
-To apply this test to a fuzz-struct you actually need another object which
-acts as a collector for many tests. This object is called Fuzz::Tests
-and is later applied to a fuzz-struct. The next example shows how you
-write some tests, assign them to the collector object and apply all
-tests to a structure.
+To apply this test to a fuzz-struct you actually need another object which
+acts as a collector for many tests. This object is called Fuzz::Tests and
+is later applied to a fuzz-struct. The next example shows how you write some
+tests, assign them to the collector object and apply all tests to a structure
+and output all permutations calculateable through these tests.
+
\begin{verbatim}
#example2.rb
require "lib/fuzz-generic"
-class Example < BitStruct
+class Example < FuzzStruct
text :example, 7
unsigned :version, 8
@@ -103,21 +148,22 @@
end
begin
- example_tests = Fuzz::Tests.new
- # tests for the text field
- example_tests.register Fuzz::Test.new("char") {|arg, size| arg} # return argument
- example_tests.register Fuzz::Test.new("char") {|arg, size| ""} # return empty string
- example_tests.register Fuzz::Test.new("char") {|arg, size| "A"*1000} # return many many A's
- # tests for unsigned numbers
+ example_tests = Fuzz::Tests.new
+
+ # tests for the text field
+ example_tests.register Fuzz::Test.new("char") {|arg, size| arg} # return argument
+ example_tests.register Fuzz::Test.new("char") {|arg, size| ""} # return empty string
+ example_tests.register Fuzz::Test.new("char") {|arg, size| "A"*1000} # return many many A's
+
+ # tests for unsigned numbers
example_tests.register Fuzz::Test.new("unsigned") {|arg, size| arg } # return argument
example_tests.register Fuzz::Test.new("unsigned") {|arg, size| 0 } # return zero
example_tests.register Fuzz::Test.new("unsigned") {|arg, size| rand(5) } # return a small number
example_tests.register Fuzz::Test.new("unsigned") {|arg, size| 2.power!(size) } # return biggest number
e = Example.new
- e.prepare! example_tests
+ e.prepare! example_tests
end
-
\end{verbatim}
\subsection{Some example tests on Tor itself}
@@ -136,6 +182,12 @@
\subsection{Dir}
\subsection{Control}
\subsection{Cell}
+\subsection{Logger}
+\subsection{Backtrace}
+\subsection{Proxy}
+\subsubsection{Http-Proxy}
+\subsubsection{Https-Proxy}
+
\section{Fuzz-Struct Reference}
\subsection{Types}
\label{types}
@@ -152,10 +204,9 @@
\subsubsection{hex-octet}
\subsubsection{nested}
\subsubsection{pad}
-\subsection{Logger}
-\appendix
+\section{Appendix}
\section{Links}
\label{links}
\begin{verbatim}
@@ -166,5 +217,4 @@
http://www.ruby-lang.org
\end{verbatim}
-\end{document}\documentclass[10pt]{article}
-
+\end{document}
Modified: topf/trunk/lib/cell.rb
===================================================================
--- topf/trunk/lib/cell.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/cell.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -10,13 +10,13 @@
[ 6, "" ] # CREATED FAST
]
- class Packet < BitStruct
+ class Packet < FuzzStruct
unsigned :circID, 16
unsigned :command, 16
rest :payload
end
- class Extended < BitStruct
+ class Extended < FuzzStruct
hex_octets :address, 32
unsigned :port, 16
rest :skin
@@ -38,7 +38,7 @@
12 => "NOSUCHSERVICE"
}
- class Relay < BitStruct
+ class Relay < FuzzStruct
unsigned :command, 8
unsigned :recognized, 16
unsigned :streamID, 16
Modified: topf/trunk/lib/control.rb
===================================================================
--- topf/trunk/lib/control.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/control.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -3,7 +3,7 @@
class ItemFuzz
attr_reader :item
def initialize(item, tests, fields, values)
- raise "item is not a BitStruct" if !item.is_a?(BitStruct)
+ raise "item is not a FuzzStruct" if !item.is_a?(FuzzStruct)
@item = item
@tests = tests
@fields = fields
@@ -94,7 +94,7 @@
=end
]
- class SetConfItem < BitStruct
+ class SetConfItem < FuzzStruct
text :item, 7
text :keyword, 30
text :assign, 1
@@ -111,7 +111,7 @@
"553 impossible configuration setting"
]
- class ResetConfItem < BitStruct
+ class ResetConfItem < FuzzStruct
text :item, 9
text :keyword, 10
text :assign, 1
@@ -121,7 +121,7 @@
initial_value.assign = "="
end
- class GetConfItem < BitStruct
+ class GetConfItem < FuzzStruct
text :item, 7
text :keyword, 10
text :assign, 1
@@ -158,7 +158,7 @@
"STREAM_BW"
]
- class SetEventsItem < BitStruct
+ class SetEventsItem < FuzzStruct
text :item, 9
text :extended, 8
@@ -174,7 +174,7 @@
"514 authentication required"
]
- class AuthenticateItem < BitStruct
+ class AuthenticateItem < FuzzStruct
text :item, 13
text :password, 8
rest :crlf
@@ -189,7 +189,7 @@
"551 Unable to write configuration to disk"
]
- class SaveConfItem < BitStruct
+ class SaveConfItem < FuzzStruct
text :item, 8
initial_value.item = "SAVECONF"
end
@@ -209,7 +209,7 @@
"CLEARDNSCACHE"
]
- class SignalItem < BitStruct
+ class SignalItem < FuzzStruct
text :item, 6
rest :signal
Modified: topf/trunk/lib/dir.rb
===================================================================
--- topf/trunk/lib/dir.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/dir.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -16,75 +16,82 @@
PublicCertificate =
%{\n-----BEGIN RSA PUBLIC KEY-----
-MIGJAoGBAKo3Ijan5HOp6zzV1VJmveh2uvJv0A5qLiJtNVrebMTAM8kte14Fsylb
-DE5UmDryqbOmNi9gIcZKfjuqEKcuhsEPDObLeabNkdP+YGURVQ72IhQT8XRiGWg3
-2i8F9xhp5KPGKhjkXuAxnt2FS9lkOvIDnm4jnOtzfX0/RJRRrBCvAgMBAAE=
+MIGJAoGBAMhnUVkFc18CmqGNEKT15xSSsZlR1JBWUTRVF7vFmPmV5uKiKfI0uW1A
+uqgYVgeXyFRuH01CYr2Ymnkf4fi3waMSDhk/FPvsx0wXuUgINnKyTOrsIycrUYSP
+DKpSF6JcCE5TsgmbK/yuDsza+3mJw7/bHg4F+aFud4pxemZDozCvAgMBAAE=
-----END RSA PUBLIC KEY-----}
- class RouterItem < BitStruct
+ class RouterItem < FuzzStruct
text :item, 6, :fuzzable => false
- text :nickname, TOPF::Dir::DefaultNicknameLength
- hex_octets :address, 32
+ text :nickname, 16
+ text :address, 13
signed :OrPort, 32
signed :SocksPort, 32
signed :DirPort, 32
initial_value.item = "router"
- initial_value.nickname = "foobar"
- initial_value.address = "127.0.0.1"
+ initial_value.nickname = "pr0xydotathdotcx"
+ initial_value.address = "88.191.37.194"
+ initial_value.OrPort = 31337
initial_value.SocksPort = 0
- initial_value.OrPort = TOPF::Dir::DefaultOrPort
- initial_value.DirPort = TOPF::Dir::DefaultDirPort
+ initial_value.DirPort = 0
end
- class PublishedItem < BitStruct
+ class PublishedItem < FuzzStruct
text :item, 9
text :time, 19
initial_value.item = "published"
- initial_value.time = "#{Date.today.to_s} #{ Time.now.strftime "%H:%M:%S"}"
+ #initial_value.time = "#{Date.today.to_s} #{ Time.now.strftime "%H:%M:%S"}"
+ initial_value.time = "2007-08-19 01:09:40"
end
- class OnionKeyItem < BitStruct
+ class OnionKeyItem < FuzzStruct
text :item, 9
- rest :publicKey # key in PEM Format
+ text :publicKey, TOPF::Dir::PublicCertificate.size # key in PEM Format
initial_value.item = "onion-key"
initial_value.publicKey = TOPF::Dir::PublicCertificate
end
- class SigningKeyItem < BitStruct
+ class SigningKeyItem < FuzzStruct
text :item, 11
- rest :publicKey # key in PEM Format
+ text :publicKey, TOPF::Dir::PublicCertificate.size # key in PEM Format
initial_value.item = "signing-key"
initial_value.publicKey = TOPF::Dir::PublicCertificate
end
- class BandwidthItem < BitStruct
+ class BandwidthItem < FuzzStruct
text :item, 9
signed :avg, 128
signed :burst, 128
signed :observed, 128
initial_value.item = "bandwidth"
- initial_value.avg = 1
- initial_value.burst = 1
- initial_value.observed = 1
+ initial_value.avg = 10240000
+ initial_value.burst = 20380000
+ initial_value.observed = 1804473
end
- class PlatformItem < BitStruct
+ class PlatformItem < FuzzStruct
text :item, 8
- rest :string
+ text :platform, 26
initial_value.item = "platform"
+ initial_value.platform = "Tor 0.1.2.16 on Linux i686"
end
- class FingerprintItem < BitStruct
- # FORMAT ??
+ class FingerprintItem < FuzzStruct
+ text :opt, 3
+ text :item, 11
+ text :fingerprint, 49
+ initial_value.opt = "opt"
+ initial_value.item = "fingerprint"
+ initial_value.fingerprint = "36A1 0B84 C5BF CDB9 BC7C 6887 7826 D676 1309 2DD6"
end
- class HibernateItem < BitStruct
+ class HibernateItem < FuzzStruct
text :item, 11
unsigned :state, 1
@@ -92,101 +99,69 @@
initial_value.state = 0
end
- class UptimeItem < BitStruct
+ class UptimeItem < FuzzStruct
text :item, 6
- # FORMAT ??
-
+ unsigned :time, 24
initial_value.item = "uptime"
+ initial_value.time = 1209373
end
- class ContactItem < BitStruct
+ class ContactItem < FuzzStruct
text :item, 7
- rest :info
+ text :info, 40
initial_value.item = "contact"
+ initial_value.info = "Felix Reinel <admin AT torproxy dot net>"
end
- class FamilyItem < BitStruct
+ class FamilyItem < FuzzStruct
text :item, 6
rest :names
initial_value.item = "family"
end
- class ReadHistoryItem < BitStruct
- text :item, 12
+ class ReadHistoryItem < FuzzStruct
+ text :item, 3
+ text :read, 12
text :time, 19
+ text :history, 968
- initial_value.item = "read-history"
- initial_value.time = "#{Date.today.to_s} #{ Time.now.strftime "%H:%M:%S"}"
+ initial_value.item = "opt"
+ initial_value.read = "read-history"
+ #initial_value.time = "#{Date.today.to_s} #{ Time.now.strftime "%H:%M:%S"}"
+ initial_value.time = "2007-08-19 01:09:37"
+ initial_value.history = "(900 s) 760098816,627098624,693427200,679235584,697864192,657379328,705751040,658093056,712881152,752723968,711652352,784343040,719242240,716414976,661498880,647461888,681280512,623717376,569185280,587918336,551035904,593421312,593065984,560878592,618540032,570112000,525900800,502802432,696317952,648034304,728816640,638992384,806351872,785328128,699988992,732289024,642468864,715794432,719076352,737125376,702242816,706820096,615213056,717157376,582617088,725468160,820884480,623130624,696113152,748891136,758933504,789217280,731297792,701725696,608859136,653759488,683127808,618695680,654241792,712316928,862899200,616518656,845710336,773454848,819221504,822200320,773602304,733693952,831583232,816207872,862288896,875128832,720563200,858846208,805805056,632126464,682014720,670363648,838111232,766550016,788750336,745674752,699387904,778595328,885575680,1049205760,821670912,735636480,781303808,982372352,1007374336,811970560,828642304,809540608,721187840,756304896"
+
end
- class WriteHistoryItem < BitStruct
- text :item, 12
+ class WriteHistoryItem < FuzzStruct
+ text :item, 3
+ text :write, 13
text :time, 19
+ text :history, 968
- initial_value.item = "write-history"
- initial_value.time = "#{Date.today.to_s} #{ Time.now.strftime "%H:%M:%S"}"
+ initial_value.item = "opt"
+ initial_value.write = "write-history"
+ #initial_value.time = "#{Date.today.to_s} #{ Time.now.strftime "%H:%M:%S"}"
+ initial_value.time = "2007-08-19 01:09:37"
+ initial_value.history = "(900 s) 758238208,625318912,691261440,663665664,680981504,641565696,690364416,642569216,695374848,737664000,706840576,780549120,715257856,713936896,660255744,623203328,646553600,618431488,566634496,585960448,550209536,593250304,590551040,558642176,616057856,568313856,525464576,500299776,694533120,641624064,695276544,628350976,789766144,764145664,681135104,717862912,625372160,702624768,694521856,709050368,673614848,680497152,588131328,690713600,561212416,723578880,816830464,619859968,693881856,743980032,756367360,785605632,730672128,697923584,594031616,625268736,655276032,615368704,649592832,706004992,858901504,613521408,844616704,771748864,817015808,819881984,770548736,730366976,829035520,813772800,859834368,869432320,716977152,856101888,803599360,629864448,680253440,668408832,836214784,764502016,785489920,744428544,696685568,777190400,883115008,1046515712,818712576,709926912,778812416,978486272,1004804096,808800256,825538560,806936576,716456960,752701440"
end
- class EventDnsItem < BitStruct
+ class RejectItem < FuzzStruct
+ text :item, 6
+ text :reject, 3
+
+ initial_value.item = "reject"
+ initial_value.reject= "*.*"
+ end
+
+ class EventDnsItem < FuzzStruct
text :item, 8
unsigned :bool, 1
-
+
initial_value.item = "eventdns"
initial_value.bool = 0
end
-
- class RouterDescriptor
- def initialize(publicKey)
- @osslkey = OpenSSL::PKey::RSA.new(File.read(publicKey) )
- @pkcs1 = PKCS1::SignatureScheme::RSASSAPKCS1v1_5.new(Digest::SHA1)
-
- @key = PKCS1::Key::RSA.new(@osslkey.n.to_i , @osslkey.e.to_i, @osslkey.d.to_i)
-
- @items = [ RouterItem.new,
- PublishedItem.new,
- OnionKeyItem.new,
- SigningKeyItem.new,
- BandwidthItem.new,
- ]
- @prepared = false
- end
-
- def add_item( item )
- @items.push item
- end
-
- def prepare_for_test
- @items.each do |item|
- Fuzz::DEFAULT_TESTS.set_struct item
- Fuzz::DEFAULT_TESTS.generate_test_data
- end
- end
-
- def fuzz!
- if !@prepared
- prepare_for_test
- @prepared = true
- end
-
- @items.each do |item|
- item.fuzz!
- end
- end
-
- def to_s
- resultString = ""
- @items.each do |item|
- resultString << item.format << "\n"
- end
- resultString << "router-signature\n"
- sig = Base64::b64encode( @pkcs1.sign(@key, resultString) )
-
- resultString << "-----BEGIN SIGNATURE-----\n"
- resultString << sig
- resultString << "-----END SIGNATURE-----" << "\n"*2
- end
- end
end
end
Modified: topf/trunk/lib/fuzz-generic.rb
===================================================================
--- topf/trunk/lib/fuzz-generic.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-generic.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -6,3 +6,4 @@
require "timeout"
require "fuzz-struct"
require "fuzz"
+require "gdb"
Modified: topf/trunk/lib/fuzz-struct/char-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/char-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/char-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,8 +1,8 @@
require 'fuzz-struct/fuzz-struct'
-class BitStruct
+class FuzzStruct
# Class for fixed length binary strings of characters.
- # Declared with BitStruct.char.
+ # Declared with FuzzStruct.char.
class CharField < Field
#def self.default
# don't define this, since it must specify N nulls and we don't know N
@@ -49,7 +49,7 @@
end
class << self
- # Define a char string field in the current subclass of BitStruct,
+ # Define a char string field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits). Trailing nulls _are_
# considered part of the string.
#
Modified: topf/trunk/lib/fuzz-struct/float-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/float-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/float-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,8 +1,8 @@
require 'fuzz-struct/fuzz-struct'
-class BitStruct
+class FuzzStruct
# Class for floats (single and double precision) in network order.
- # Declared with BitStruct.float.
+ # Declared with FuzzStruct.float.
class FloatField < Field
# Used in describe.
def self.class_name
@@ -62,7 +62,7 @@
end
class << self
- # Define a floating point field in the current subclass of BitStruct,
+ # Define a floating point field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits).
#
# If a class is provided, use it for the Field class.
Modified: topf/trunk/lib/fuzz-struct/fuzz-struct.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/fuzz-struct.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/fuzz-struct.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -8,7 +8,7 @@
# Note that all string methods are still available: length, grep, etc.
# The String#replace method is useful.
#
-class BitStruct < String
+class FuzzStruct < String
class Field
# Offset of field in bits.
attr_reader :offset
@@ -37,10 +37,10 @@
attr_reader :fuzzable
# Subclasses can override this to define a default for all fields of this
- # class, not just the one currently being added to a BitStruct class, a
+ # class, not just the one currently being added to a FuzzStruct class, a
# "default default" if you will. The global default, if #default returns
# nil, is to fill the field with zero. Most field classes just let this
- # default stand. The default can be overridden per-field when a BitStruct
+ # default stand. The default can be overridden per-field when a FuzzStruct
# class is defined.
def self.default; nil; end
@@ -83,7 +83,7 @@
@display_name = opts[:display_name] || opts["display_name"]
@default = opts[:default] || opts["default"] || self.class.default
@format = opts[:format] || opts["format"]
-
+
if opts.has_key?(:fuzzable) || opts.has_key?("fuzzable")
@fuzzable = opts[:fuzzable] || opts["fuzzable"]
else
@@ -147,7 +147,7 @@
# Return the list of fields for this class including the rest field.
def fields
- @fields ||= self == BitStruct ? [] : superclass.fields.dup
+ @fields ||= self == FuzzStruct ? [] : superclass.fields.dup
end
@@ -157,7 +157,7 @@
@own_fields ||= []
end
- # Add a field to the BitStruct (usually, this is only used internally).
+ # Add a field to the FuzzStruct (usually, this is only used internally).
def add_field(name, length, opts = {})
round_byte_length ## just to make sure this has been calculated
## before adding anything
@@ -166,7 +166,7 @@
if @closed
raise ClosedClassError, "Cannot add field #{name}: " +
- "The definition of the #{self.inspect} BitStruct class is closed."
+ "The definition of the #{self.inspect} FuzzStruct class is closed."
end
if fields.find {|f|f.name == name}
@@ -266,7 +266,7 @@
# ------------------------
# :section: metadata inspection methods
#
- # Methods to textually describe the format of a BitStruct subclass.
+ # Methods to textually describe the format of a FuzzStruct subclass.
#
# ------------------------
@@ -280,7 +280,7 @@
DESCRIBE_FORMAT
end
- # Textually describe the fields of this class of BitStructs.
+ # Textually describe the fields of this class of FuzzStructs.
# Returns a printable table (array of line strings), based on +fmt+,
# which defaults to #describe_format, which defaults to +DESCRIBE_FORMAT+.
def describe(fmt = nil, opts = {})
@@ -331,7 +331,7 @@
# ------------------------
# Initialize the string with the given string or bitstruct, or with a hash of
- # field=>value pairs, or with the defaults for the BitStruct subclass. Fields
+ # field=>value pairs, or with the defaults for the FuzzStruct subclass. Fields
# can be strings or symbols. Finally, if a block is given, yield the instance
# for modification using accessors.
def initialize(value = nil) # :yields: instance
@@ -385,7 +385,7 @@
end
end
- # Returns an array of values of the fields of the BitStruct. By default,
+ # Returns an array of values of the fields of the FuzzStruct. By default,
# include the rest field.
def to_a(include_rest = true)
ary =
@@ -429,10 +429,10 @@
@initial_value
end
- # Take +data+ (a string or BitStruct) and parse it into instances of
+ # Take +data+ (a string or FuzzStruct) and parse it into instances of
# the +classes+, returning them in an array. The classes can be given
# as an array or a separate arguments. (For parsing a string into a _single_
- # BitStruct instance, just use the #new method with the string as an arg.)
+ # FuzzStruct instance, just use the #new method with the string as an arg.)
def parse(data, *classes)
classes.flatten.map do |c|
c.new(data.slice!(0...c.round_byte_length))
@@ -496,31 +496,33 @@
raise "argument must be of class Tests" if !tests.is_a?(Fuzz::Tests)
result = []
self.fields.each do |field|
- arg = self.method(field.name).call
- if field.fuzzable
- temp = []
- length = field.length
- case field.class.to_s
- when "BitStruct::SignedField"
- tests.signed_tests.each do |test|
- temp.push( test.run(arg, length) )
- end
- result.push(temp)
- when "BitStruct::UnsignedField"
- tests.unsigned_tests.each do |test|
- temp.push( test.run(arg, length) )
- end
- result.push(temp)
- when "BitStruct::TextField", "BitStruct::CharField", "BitStruct::Field"
- tests.char_tests.each do |test|
+ if field
+ arg = self.method(field.name).call
+ if field.fuzzable
+ temp = []
+ length = field.length
+ case field.class.to_s
+ when "FuzzStruct::SignedField"
+ tests.signed_tests.each do |test|
temp.push( test.run(arg, length) )
+ end
+ result.push(temp)
+ when "FuzzStruct::UnsignedField"
+ tests.unsigned_tests.each do |test|
+ temp.push( test.run(arg, length) )
+ end
+ result.push(temp)
+ when "FuzzStruct::TextField", "FuzzStruct::CharField", "FuzzStruct::Field"
+ tests.char_tests.each do |test|
+ temp.push( test.run(arg, length) )
+ end
+ result.push(temp)
+ else
+ Fuzz::LOGGER.debug "new field-type: %s" % field.class.to_s
end
- result.push(temp)
else
- Fuzz::LOGGER.debug "new field-type: %s" % field.class.to_s
+ result.push( [ arg ] )
end
- else
- result.push( [ arg ] )
end
end
@tests = result
@@ -529,9 +531,8 @@
sizes = @tests.collect {|element| element.size}
@dimension = sizes.inject(1){|prod, element| prod*element }
-
+
permutations = Array.new(sizes.size, Array.new(@dimension, 0) )
-
result = []
permutations.each_with_index do |element, index|
count = 0
@@ -551,15 +552,13 @@
Fuzz::LOGGER.debug "[x] calculated %d permutations of struct %s" % [result.first.size, self.class]
@permutations = result
-=begin
-# debugging stuff
- @permutations[0].each_with_index do |element, index|
- pp @permutations.collect{|el| el[index] }
- end
-=end
@permutation_index = 0
end
+ def permutations
+ @permutations.first.size
+ end
+
def fuzz!(opts = DEFAULT_INSPECT_OPTS)
raise "no tests have been generated yet" if !@permutations or !@tests
raise "end of tests" if @permutation_index.to_i == @dimension.to_i
@@ -576,16 +575,29 @@
ret
end
+ def output(join_char = "")
+ opts = DEFAULT_INSPECT_OPTS
+ fields_for_output = fields.select {|field| field.inspectable? if field}
+
+ if opts[:include_rest] and (rest_field = self.class.rest_field)
+ fields_for_output << rest_field
+ end
+
+ test = fields_for_output.map { |field|
+ field.to_s(self, opts)
+ }.join(join_char)
+ end
+
def format(opts = DEFAULT_INSPECT_OPTS)
- fields_for_output = fields.select {|field| field.inspectable?}
+ fields_for_output = fields.select {|field| field.inspectable? if field}
if opts[:include_rest] and (rest_field = self.class.rest_field)
fields_for_output << rest_field
end
-
+
fields_for_output.map { |field|
field.to_s(self, opts)
- }.join " "
+ }.join
end
# A more visually appealing inspect method that puts each field/value on
@@ -603,13 +615,13 @@
# ------------------------
# Define accessors for a variable length substring from the end of
- # the defined fields to the end of the BitStruct. The _rest_ may behave as
- # a String or as some other String or BitStruct subclass.
+ # the defined fields to the end of the FuzzStruct. The _rest_ may behave as
+ # a String or as some other String or FuzzStruct subclass.
#
# This does not add a field, which is useful because a superclass can have
# a rest method which accesses subclass data. In particular, #rest does
# not affect the #round_byte_length class method. Of course, any data
- # in rest does add to the #length of the BitStruct, calculated as a string.
+ # in rest does add to the #length of the FuzzStruct, calculated as a string.
# Also, _rest_ is not inherited.
#
# The +ary+ argument(s) work as follows:
Modified: topf/trunk/lib/fuzz-struct/hex-octet-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/hex-octet-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/hex-octet-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,13 +1,13 @@
require 'fuzz-struct/char-field'
-class BitStruct
+class FuzzStruct
# Class for char fields that can be accessed with values like
# "xx:xx:xx:xx", where each xx is up to 2 hex digits representing a
# single octet. The original string-based accessors are still available with
# the <tt>_chars</tt> suffix.
#
- # Declared with BitStruct.hex_octets.
- class HexOctetField < BitStruct::OctetField
+ # Declared with FuzzStruct.hex_octets.
+ class HexOctetField < FuzzStruct::OctetField
# Used in describe.
def self.class_name
@class_name ||= "hex_octets"
@@ -19,7 +19,7 @@
end
class << self
- # Define an octet string field in the current subclass of BitStruct,
+ # Define an octet string field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits). Trailing nulls are
# not considered part of the string. The field is accessed using
# period-separated hex digits.
Modified: topf/trunk/lib/fuzz-struct/nested-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/nested-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/nested-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,8 +1,8 @@
require 'fuzz-struct/fuzz-struct'
-class BitStruct
- # Class for nesting a BitStruct as a field within another BitStruct.
- # Declared with BitStruct.nest.
+class FuzzStruct
+ # Class for nesting a FuzzStruct as a field within another FuzzStruct.
+ # Declared with FuzzStruct.nest.
class NestedField < Field
attr_reader :nested_class
@@ -78,7 +78,7 @@
end
class << self
- # Define a nested field in the current subclass of BitStruct,
+ # Define a nested field in the current subclass of FuzzStruct,
# with the given _name_ and _nested_class_. Length is determined from
# _nested_class_.
#
@@ -93,11 +93,11 @@
#
# For example:
#
- # class Sub < BitStruct
+ # class Sub < FuzzStruct
# unsigned :x, 8
# end
#
- # class A < BitStruct
+ # class A < FuzzStruct
# nest :n, Sub
# end
#
Modified: topf/trunk/lib/fuzz-struct/octet-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/octet-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/octet-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,13 +1,13 @@
require 'fuzz-struct/char-field'
-class BitStruct
+class FuzzStruct
# Class for char fields that can be accessed with values like
# "xxx.xxx.xxx.xxx", where each xxx is up to 3 decimal digits representing a
# single octet. The original string-based accessors are still available with
# the <tt>_chars</tt> suffix.
#
- # Declared with BitStruct.octets.
- class OctetField < BitStruct::CharField
+ # Declared with FuzzStruct.octets.
+ class OctetField < FuzzStruct::CharField
# Used in describe.
def self.class_name
@class_name ||= "octets"
@@ -44,7 +44,7 @@
end
class << self
- # Define an octet string field in the current subclass of BitStruct,
+ # Define an octet string field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits). Trailing nulls are
# not considered part of the string. The field is accessed using
# period-separated decimal digits.
Modified: topf/trunk/lib/fuzz-struct/pad-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/pad-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/pad-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,6 +1,6 @@
require 'fuzz-struct/fuzz-struct'
-class BitStruct
+class FuzzStruct
# Class for fixed length padding.
class PadField < Field
# Used in describe.
@@ -16,7 +16,7 @@
end
class << self
- # Define a padding field in the current subclass of BitStruct,
+ # Define a padding field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits).
#
# If a class is provided, use it for the Field class.
Modified: topf/trunk/lib/fuzz-struct/signed-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/signed-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/signed-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,8 +1,8 @@
require 'fuzz-struct/fuzz-struct'
-class BitStruct
+class FuzzStruct
# Class for signed integers in network order, 1-16 bits, or 8n bits.
- # Declared with BitStruct.signed.
+ # Declared with FuzzStruct.signed.
class SignedField < Field
# Used in describe.
def self.class_name
@@ -214,7 +214,7 @@
end
class << self
- # Define a signed integer field in the current subclass of BitStruct,
+ # Define a signed integer field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits).
#
# If a class is provided, use it for the Field class.
Modified: topf/trunk/lib/fuzz-struct/text-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/text-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/text-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,8 +1,8 @@
require 'fuzz-struct/fuzz-struct'
-class BitStruct
+class FuzzStruct
# Class for null-terminated printable text strings.
- # Declared with BitStruct.text.
+ # Declared with FuzzStruct.text.
class TextField < Field
# Used in describe.
def self.class_name
@@ -45,7 +45,7 @@
end
class << self
- # Define a printable text string field in the current subclass of BitStruct,
+ # Define a printable text string field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits). Trailing nulls are
# _not_ considered part of the string.
#
Modified: topf/trunk/lib/fuzz-struct/unsigned-field.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/unsigned-field.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/unsigned-field.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,8 +1,8 @@
require 'fuzz-struct/fuzz-struct'
-class BitStruct
+class FuzzStruct
# Class for unsigned integers in network order, 1-16 bits, or 8n bits.
- # Declared with BitStruct.unsigned.
+ # Declared with FuzzStruct.unsigned.
class UnsignedField < Field
# Used in describe.
def self.class_name
@@ -204,7 +204,7 @@
end
class << self
- # Define a unsigned integer field in the current subclass of BitStruct,
+ # Define a unsigned integer field in the current subclass of FuzzStruct,
# with the given _name_ and _length_ (in bits).
#
# If a class is provided, use it for the Field class.
Modified: topf/trunk/lib/fuzz-struct/yaml.rb
===================================================================
--- topf/trunk/lib/fuzz-struct/yaml.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz-struct/yaml.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,7 +1,7 @@
require 'fuzz-struct/fuzz-struct'
require 'yaml'
-class BitStruct
+class FuzzStruct
if RUBY_VERSION == "1.8.2"
def is_complex_yaml? # :nodoc:
true
@@ -40,7 +40,7 @@
props
end
- # Return YAML representation of the BitStruct.
+ # Return YAML representation of the FuzzStruct.
def to_yaml( opts = {} )
YAML::quick_emit( object_id, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
@@ -53,10 +53,10 @@
def self.yaml_new( klass, tag, val ) # :nodoc:
unless Hash === val
- raise YAML::TypeError, "Invalid BitStruct: " + val.inspect
+ raise YAML::TypeError, "Invalid FuzzStruct: " + val.inspect
end
- bitstruct_name, bitstruct_type = YAML.read_type_class( tag, BitStruct )
+ bitstruct_name, bitstruct_type = YAML.read_type_class( tag, FuzzStruct )
st = bitstruct_type.new
Modified: topf/trunk/lib/fuzz.rb
===================================================================
--- topf/trunk/lib/fuzz.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/fuzz.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,54 +1,135 @@
+class String
+ # insert! copies the string before altering it compared to the normal insert
+ # method
+ def insert!(index, inject)
+ self.clone.insert(index, inject)
+ end
+end
+
module Fuzz
+ # define your own if you want :)
MAX_RAND = 1000
+ # This Class collects many FuzzStructs and takes a block to calculate the
+ # wanted output of everything.
class Collection
- def initialize
- @structs = []
+ attr_reader :structs, :number_of_tests
+ def initialize(join_character = "")
+ @join_character = join_character
+ @structs = Array.new
+ @format_block = nil
+ @prepared = false
+ @fuzz_index = 0
+ @number_of_tests = 0
end
- def add(struct)
- raise "argument must be a Fuzz::Test object" if !struct.is_a?(BitStruct)
- @structs.push struct
+
+ # adds a FuzzStruct to the collection
+ def add_struct(struct)
+ @structs << struct if struct
end
- # fuzzes only one struct at the time
- def linear_fuzz
+
+ # apply tests to all objects in the collection
+ def add_tests(tests)
+ raise "argument must be a Fuzz::Tests object" if !tests.is_a?(Fuzz::Tests)
@structs.each do |struct|
-
+ struct.prepare! tests
+ @number_of_tests += struct.permutations
end
+ @prepared = true
end
- # joins all structs together but only fuzzes one struct after another
- def join_fuzz
+
+ def add_format_block(&block)
+ @format_block = block
end
+
+ def fuzz!(args)
+ raise "no tests have been added yet" if !@prepared
+ args[:fuzz_index] = @fuzz_index
+ resultString, @fuzz_index = to_s( args )
+ @number_of_tests-=1
+ [ resultString, @number_of_tests]
+ end
+
+ # supply a block on howto format the collection
+ def to_s(args)
+ raise "no format block given yet!" if !@format_block
+ @format_block.call(args, @structs, @join_character)
+ end
end
- class BinaryObserver
- def initialize( programname, *arguments )
+ class BinaryObserver
+ attr_reader :coremanager
+ def initialize( programname, corepath, *arguments )
@programname = programname
@arguments = arguments.to_a
@pid = nil
+ @coremanager = Fuzz::CoreManager.new(@programname, corepath)
+ @running = false
end
+
def observe!
- @pid = fork do
- trap("CLD") do
- pid = Process.wait
- puts "Child pid #{pid}: terminated"
- process_status = $?
+ Thread.new do
+ @pid = fork do
+ Fuzz::LOGGER.info "[x] starting #{@programname} #{@arguments.join(" ")}"
+ exec("#{@programname} #{@arguments.join(" ")} ")
end
- Fuzz::LOGGER.info "[x] starting #{@programname}"
- system("#{@programname} #{@arguments.join(" ")} ")
+ @running = true
+ Process.wait
+ Fuzz::LOGGER.debug "[!] %d coredumped? %s" % [@pid, process_status.coredump?]
+ Fuzz::LOGGER.debug "[!] %d get uncaught signal %d" % [@pid, process_status.termsig] if process_status.signaled?
+ Fuzz::LOGGER.debug "[!] %d stopped by signal %d" % [@pid, process_status.stopsig] if process_status.stopped?
+ Fuzz::LOGGER.debug "[!] %d exited %d" % [@pid, process_status.exitstatus] if process_status.exited?
+ @running = false
end
- # Fuzz::LOGGER.debug "[!] %d coredumped? %s" % [@pid, process_status.coredump?]
- # Fuzz::LOGGER.debug "[!] %d get uncaught signal %d" % [@pid, process_status.termsig] if process_status.signaled?
- # Fuzz::LOGGER.debug "[!] %d stopped by signal %d" % [@pid, process_status.stopsig] if process_status.stopped?
- # Fuzz::LOGGER.debug "[!] %d exited %d" % [@pid, process_status.exitstatus] if process_status.exited?
end
def get_pid
@pid
end
def exit
- Process.kill "KILL", @pid
+ Process.kill "KILL", @pid if @running
end
end
+ class CoreManager
+ def initialize(executable, corepath)
+ @executable = executable
+ @corepath = corepath
+ @list = get_corefiles
+ enable_coredump
+ end
+
+ def latest_corefile
+ @list.last
+ end
+
+ def new_corefile?
+ new = get_corefiles
+ if new.size > 0 && new != @list
+ @list = new
+ true
+ else
+ false
+ end
+ end
+
+ def get_latest_backtrace
+ GDB::Interface.new( {:executable => @executable, :core => @corepath+"/"+ at list.last} ).bt if @list
+ end
+
+ def get_latest_registers
+ GDB::Interface.new( {:executable => @executable, :core => @corepath+"/"+ at list.last} ).info("registers") if @list
+ end
+
+ def enable_coredump
+ system("ulimit -c unlimited")
+ end
+ private
+
+ def get_corefiles
+ Dir.new(File.expand_path(@corepath)).entries.select{|entry| entry=~/core/ }.sort{|x, y| File.mtime(@corepath+"/"+x) <=> File.mtime(@corepath+"/"+y)}
+ end
+ end
+
# This Class holds all tests to related to a given field-type
class Tests
attr_reader :tests, :permutations, :signed_tests, :char_tests, :unsigned_tests
@@ -143,6 +224,11 @@
temp.push( test.run(arg, length) )
end
result.push(temp)
+ when "BitStruct::HexOctetField"
+ @hex_tests.each do |test|
+ temp.push( test.run(arg, length) )
+ end
+ result.push(temp)
else
Fuzz::LOGGER.debug "new field-type: %s" % field.class.to_s
end
@@ -200,15 +286,55 @@
@test.call arg, size
end
end
-
- def Fuzz.coreObserver(file)
- if Dir.new(File.expand_path(File.dirname(file)) ).entries.select{|x| x=~/\.core/}.size != 0
- return true
- else
- return false
+
+ def Fuzz.fuzz_iterator(struct, &block)
+ while true
+ block.call( struct.fuzz! )
end
end
+ def Fuzz.fuzz(observer, struct, &block)
+ begin
+ Fuzz::fuzz_iterator(struct, &block)
+ rescue Exception => exception
+ Fuzz::LOGGER.info "[?] error while sending data:\n%s\n" % data
+ Fuzz::LOGGER.info "[?] locking for new corefiles.."
+ if observer.coremanager.new_corefile?
+ Fuzz::LOGGER.info "[?] found new corefile(%s)\nprinting backtrace:\n%s\nprinting registers:\n%s" % [ observer.coremanager.latest_corefile, observer.coremanager.get_latest_backtrace, observer.coremanager.get_latest_registers ]
+ else
+ Fuzz::LOGGER.info "[?] no new corefile found"
+ end
+ Kernel::exit
+ end
+ end
+
+ def Fuzz.argument(application, struct, config)
+ reg = Regexp.new "outch!"
+ coremanager = Fuzz::CoreManager.new(application, config["COREDIR"])
+ begin
+ Fuzz::fuzz_iterator(struct){|argument|
+ argument = argument.join if argument.is_a?(Array)
+ system(application + " " + argument)
+ raise "outch!\n%s" % argument if coremanager.new_corefile?
+ }
+ rescue Exception => exception
+ if exception.to_s =~ reg
+ argument = exception.to_s.gsub("outch!", "")
+ puts "!"*40
+ puts "argument:\n%s \nkilled the application!" % argument
+ puts "backtrace:"
+ puts coremanager.get_latest_backtrace
+ puts "_"*40
+ puts "registers:"
+ puts coremanager.get_latest_registers
+ puts "writing POC"
+ File.open("POC", "w+").write "#!/bin/sh\n#{application.strip} #{argument.strip}"
+ puts "!"*40
+ end
+ Kernel::exit
+ end
+ end
+
# makes a Connection to a given target and sends our raw data to it
# see yourself what options are needed :>
class Connection
@@ -219,7 +345,7 @@
@path = args[:path]
@http_direction = args[:http_direction]
@http_url = args[:http_url]
- @object = args[:object]
+ @observer = args[:observer]
args[:timeout] ? @timeout = args[:timeout] : @timeout = 0.2
Fuzz::LOGGER.level = Logger::INFO if !args[:debug]
@@ -243,18 +369,15 @@
def fuzz!(structs, join_character="", args={})
structs = [structs] if !structs.is_a? Array
- structs.each do |struct|
- begin
- while true
- data = struct.fuzz!.join( join_character )
- Fuzz::LOGGER.debug "sending data: %s" % data
- self.send data
- assert(args[:assert] )
- end
- rescue Exception => exception
- Fuzz::LOGGER.debug "[!] ERROR: %s" % $!
- Fuzz::LOGGER.debug "[!] \n%s" % exception.backtrace.join("\n")
- end
+ structs.each_with_index do |struct, index|
+ Fuzz::LOGGER.info "[x] fuzzing struct %d of %d with %d permutations" % [index+1, structs.size, 0]
+
+ Fuzz.fuzz(@observer, struct){|struct|
+ data = struct.join( join_character )
+ Fuzz::LOGGER.debug "sending data: %s" % data
+ self.send data
+ assert(args[:assert] )
+ }
end
raise "finished all tests"
end
@@ -263,9 +386,8 @@
def assert(reply = [])
begin
timeout(@timeout) do
- reply_data = @socket.readline()
- raise "ASSERTION %s FAILED" % reply.join(",") if !reply.include?(reply_data.strip)
- Fuzz::LOGGER.debug "reply: %s" % reply_data
+ reply_data = Regexp.new( @socket.readline() )
+ raise "ASSERTION %s FAILED\nreceived %s" % [ reply.join(","), reply_data] if !reply.find_all{|x| x=~ reply_data}
end
rescue Exception
Fuzz::LOGGER.debug "[!] Exception: %s" % $!
@@ -302,9 +424,27 @@
DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| "" } # Return empty String
DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| "A"*arg.size } # FAULTING ARGUMENT STRING
DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| "A"*Fuzz::MAX_RAND } # LONG STRING
- DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| "%n"*Fuzz::MAX_RAND } # FORMAT STRING
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!(arg.size/2, "%n"*23) } # FORMAT STRING
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| "\n" } # newline
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "\n" ) } # neeline insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| "\r\n" } # newline
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "\r\n" ) } # newline insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| "\0" } # nullbyte
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "\0" ) } # nullbyte insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "=" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "/" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "\\" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "," ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, ";" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "{" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "}" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "[" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "]" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, "(" ) } # assign insert!
+ DEFAULT_TESTS.register Fuzz::Test.new("char") {|arg, size| arg.insert!( arg.size/2, ")" ) } # assign insert!
# Tests for signed numbers
+ DEFAULT_TESTS.register Fuzz::Test.new("signed") {|arg, size| arg } # return zero
DEFAULT_TESTS.register Fuzz::Test.new("signed") {|arg, size| 0 } # return zero
DEFAULT_TESTS.register Fuzz::Test.new("signed") {|arg, size| rand(5) } # return a small number
DEFAULT_TESTS.register Fuzz::Test.new("signed") {|arg, size| -1 } # return -1
@@ -312,6 +452,7 @@
DEFAULT_TESTS.register Fuzz::Test.new("signed") {|arg, size| -(2.power!(size)/2) } # smallest 2s complement number
# Tests for unsigned numbers
+ DEFAULT_TESTS.register Fuzz::Test.new("unsigned") {|arg, size| arg } # return zero
DEFAULT_TESTS.register Fuzz::Test.new("unsigned") {|arg, size| 0 } # return zero
DEFAULT_TESTS.register Fuzz::Test.new("unsigned") {|arg, size| rand(5) } # return a small number
DEFAULT_TESTS.register Fuzz::Test.new("unsigned") {|arg, size| 2.power!(size) } # return biggest number
Modified: topf/trunk/lib/pkcs1.rb
===================================================================
--- topf/trunk/lib/pkcs1.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/pkcs1.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -20,808 +20,732 @@
module PKCS1
+ # 1 Introduction
+ # 2 Notation
+ module Util
+ module_function
-# 1 Introduction
+ def nbits(num)
+ idx = num.size * 8 - 1
+ while idx >= 0
+ if num[idx].nonzero?
+ return idx + 1
+ end
+ idx -= 1
+ end
+ 0
+ end
+ def divceil(a, b)
+ (a + b - 1) / b
+ end
-# 2 Notation
-
-module Util
-module_function
-
- def nbits(num)
- idx = num.size * 8 - 1
- while idx >= 0
- if num[idx].nonzero?
- return idx + 1
- end
- idx -= 1
+ def xor(a, b)
+ if a.size != b.size
+ raise ArgumentError
+ end
+ ary = []
+ a.size.times do |idx|
+ ary << (a[idx] ^ b[idx])
+ end
+ ary.pack("c*")
+ end
end
- 0
- end
- def divceil(a, b)
- (a + b - 1) / b
- end
- def xor(a, b)
- if a.size != b.size
- raise ArgumentError
- end
- ary = []
- a.size.times do |idx|
- ary << (a[idx] ^ b[idx])
- end
- ary.pack("c*")
- end
-end
+ # 3 Key types
+ module Key
+ class RSAPublicKey
+ attr_reader :n
+ attr_reader :e
+ def initialize(n, e)
+ @n, @e = n, e
+ @n_bn = OpenSSL::BN.new(@n.to_s)
+ @e_bn = OpenSSL::BN.new(@e.to_s)
+ end
-# 3 Key types
-module Key
- class RSAPublicKey
- attr_reader :n
- attr_reader :e
+ def encrypt(m)
+ calc(m)
+ end
- def initialize(n, e)
- @n, @e = n, e
- @n_bn = OpenSSL::BN.new(@n.to_s)
- @e_bn = OpenSSL::BN.new(@e.to_s)
- end
+ # M = S ^ e (mod n)
+ def verify(s)
+ if s < 0 or s >= @n
+ raise ArgumentError, "signature representative out of range"
+ end
+ calc(s)
+ end
- def encrypt(m)
- calc(m)
- end
+ private
- # M = S ^ e (mod n)
- def verify(s)
- if s < 0 or s >= @n
- raise ArgumentError, "signature representative out of range"
- end
- calc(s)
- end
+ # c = m ^ e (mod n)
+ def calc(input)
+ input_bn = OpenSSL::BN.new(input.to_s)
+ (input_bn.mod_exp(@e_bn, @n_bn)).to_i
+ end
+ end
- private
- # c = m ^ e (mod n)
- def calc(input)
- input_bn = OpenSSL::BN.new(input.to_s)
- (input_bn.mod_exp(@e_bn, @n_bn)).to_i
- end
- end
+ class RSAPrivateKey
+ include Util
+ attr_reader :public_key
+ attr_reader :version
+ attr_reader :n
+ attr_reader :d
- class RSAPrivateKey
- include Util
+ def initialize(n, e, d)
+ @version = 0
+ @n, @d = n, d
+ @n_bn = OpenSSL::BN.new(@n.to_s)
+ @d_bn = OpenSSL::BN.new(@d.to_s)
+ @public_key = RSAPublicKey.new(n, e)
+ end
- attr_reader :public_key
- attr_reader :version
- attr_reader :n
- attr_reader :d
+ def modbytes
+ divceil(modbits, 8)
+ end
- def initialize(n, e, d)
- @version = 0
- @n, @d = n, d
- @n_bn = OpenSSL::BN.new(@n.to_s)
- @d_bn = OpenSSL::BN.new(@d.to_s)
- @public_key = RSAPublicKey.new(n, e)
- end
+ def modbits
+ nbits(@n)
+ end
- def modbytes
- divceil(modbits, 8)
- end
+ def encrypt(m)
+ @public_key.encrypt(m)
+ end
- def modbits
- nbits(@n)
- end
+ def decrypt(c)
+ calc(c)
+ end
- def encrypt(m)
- @public_key.encrypt(m)
- end
+ def sign(m)
+ if m < 0 or m >= @n
+ raise ArgumentError, "message representative out of range"
+ end
+ calc(m)
+ end
- def decrypt(c)
- calc(c)
- end
+ def verify(s)
+ @public_key.verify(s)
+ end
- def sign(m)
- if m < 0 or m >= @n
- raise ArgumentError, "message representative out of range"
- end
- calc(m)
- end
+ private
- def verify(s)
- @public_key.verify(s)
- end
+ # s = m ^ d (mod n)
+ def calc(input)
+ input_bn = OpenSSL::BN.new(input.to_s)
+ (input_bn.mod_exp(@d_bn, @n_bn)).to_i
+ end
+ end
- private
- # s = m ^ d (mod n)
- def calc(input)
- input_bn = OpenSSL::BN.new(input.to_s)
- (input_bn.mod_exp(@d_bn, @n_bn)).to_i
- end
- end
+ class RSACRTPrivateKey
+ include Util
+ attr_reader :public_key
+ attr_reader :version
+ attr_reader :n
+ attr_reader :p
+ attr_reader :q
+ attr_reader :dp
+ attr_reader :dq
+ attr_reader :qinv
- class RSACRTPrivateKey
- include Util
+ def initialize(n, e, p, q, dp, dq, qinv)
+ @version = 0
+ @n = n
+ @n_bn = OpenSSL::BN.new(@n.to_s)
+ @p, @q, @dp, @dq, @qinv = p, q, dp, dq, qinv
+ @p_bn = OpenSSL::BN.new(@p.to_s)
+ @q_bn = OpenSSL::BN.new(@q.to_s)
+ @dp_bn = OpenSSL::BN.new(@dp.to_s)
+ @dq_bn = OpenSSL::BN.new(@dq.to_s)
+ @qinv_bn = OpenSSL::BN.new(@qinv.to_s)
+ @public_key = RSAPublicKey.new(n, e)
+ end
- attr_reader :public_key
- attr_reader :version
- attr_reader :n
- attr_reader :p
- attr_reader :q
- attr_reader :dp
- attr_reader :dq
- attr_reader :qinv
+ def modbytes
+ divceil(modbits, 8)
+ end
- def initialize(n, e, p, q, dp, dq, qinv)
- @version = 0
- @n = n
- @n_bn = OpenSSL::BN.new(@n.to_s)
- @p, @q, @dp, @dq, @qinv = p, q, dp, dq, qinv
- @p_bn = OpenSSL::BN.new(@p.to_s)
- @q_bn = OpenSSL::BN.new(@q.to_s)
- @dp_bn = OpenSSL::BN.new(@dp.to_s)
- @dq_bn = OpenSSL::BN.new(@dq.to_s)
- @qinv_bn = OpenSSL::BN.new(@qinv.to_s)
- @public_key = RSAPublicKey.new(n, e)
- end
+ def modbits
+ nbits(@n)
+ end
- def modbytes
- divceil(modbits, 8)
- end
+ def encrypt(m)
+ @public_key.encrypt(m)
+ end
- def modbits
- nbits(@n)
- end
+ def decrypt(c)
+ calc(c)
+ end
- def encrypt(m)
- @public_key.encrypt(m)
- end
+ def sign(m)
+ if m < 0 or m >= @n
+ raise ArgumentError, "message representative out of range"
+ end
+ calc(m)
+ end
- def decrypt(c)
- calc(c)
- end
+ def verify(s)
+ @public_key.verify(s)
+ end
- def sign(m)
- if m < 0 or m >= @n
- raise ArgumentError, "message representative out of range"
- end
- calc(m)
- end
+ private
- def verify(s)
- @public_key.verify(s)
- end
+ # s1 = m ^ dp (mod p)
+ # s2 = m ^ dq (mod q)
+ # h = (s1 - s2) * qinv (mod p)
+ # s = s2 + q * h
+ def calc(input)
+ input_bn = OpenSSL::BN.new(input.to_s)
+ s1 = input_bn.mod_exp(@dp_bn, @p_bn)
+ s2 = input_bn.mod_exp(@dq_bn, @q_bn)
+ h = @qinv_bn.mod_mul(s1 - s2, @p_bn)
+ (s2 + q * h).to_i
+ end
+ end
- private
- # s1 = m ^ dp (mod p)
- # s2 = m ^ dq (mod q)
- # h = (s1 - s2) * qinv (mod p)
- # s = s2 + q * h
- def calc(input)
- input_bn = OpenSSL::BN.new(input.to_s)
- s1 = input_bn.mod_exp(@dp_bn, @p_bn)
- s2 = input_bn.mod_exp(@dq_bn, @q_bn)
- h = @qinv_bn.mod_mul(s1 - s2, @p_bn)
- (s2 + q * h).to_i
+ RSA = RSAPrivateKey
+ RSACRT = RSACRTPrivateKey
end
- end
- RSA = RSAPrivateKey
- RSACRT = RSACRTPrivateKey
-end
+ # 4 Data conversion primitives
+ module DataConversion
+ module_function
-
-# 4 Data conversion primitives
-module DataConversion
-module_function
-
- # Integer to Octet String primitive
- def i2osp(x, len)
- if x >= 256 ** len
- raise ArgumentError, "integer too large"
- end
- os = to_bytes(x).sub(/^\x00+/, '')
+ # Integer to Octet String primitive
+ def i2osp(x, len)
+ if x >= 256 ** len
+ raise ArgumentError, "integer too large"
+ end
+ os = to_bytes(x).sub(/^\x00+/, '')
"\x00" * (len - os.size) + os
- end
+ end
- # Octet String to Integer primitive
- def os2ip(x)
- from_bytes(x)
- end
+ # Octet String to Integer primitive
+ def os2ip(x)
+ from_bytes(x)
+ end
- def to_bytes(num)
- bits = num.size * 8
- pos = value = 0
- str = ""
- for idx in 0..(bits - 1)
- if num[idx].nonzero?
- value |= (num[idx] << pos)
- end
- pos += 1
- if pos == 32
- str = [value].pack("N") + str
- pos = value = 0
- end
- end
- str
- end
+ def to_bytes(num)
+ bits = num.size * 8
+ pos = value = 0
+ str = ""
+ for idx in 0..(bits - 1)
+ if num[idx].nonzero?
+ value |= (num[idx] << pos)
+ end
+ pos += 1
+ if pos == 32
+ str = [value].pack("N") + str
+ pos = value = 0
+ end
+ end
+ str
+ end
- def from_bytes(bytes)
- num = 0
- bytes.each_byte do |c|
- num <<= 8
- num |= c
+ def from_bytes(bytes)
+ num = 0
+ bytes.each_byte do |c|
+ num <<= 8
+ num |= c
+ end
+ num
+ end
end
- num
- end
-end
-# 5 Cryptographic primitives
-module CryptographicPrimitive
-module_function
+ # 5 Cryptographic primitives
+ module CryptographicPrimitive
+ module_function
- def rsaep(key, msg)
- key.encrypt(msg)
- end
+ def rsaep(key, msg)
+ key.encrypt(msg)
+ end
- def rsadp(key, cipher)
- key.decrypt(cipher)
- end
+ def rsadp(key, cipher)
+ key.decrypt(cipher)
+ end
- def rsasp1(key, msg)
- key.sign(msg)
- end
+ def rsasp1(key, msg)
+ key.sign(msg)
+ end
- def rsavp1(key, sig)
- key.verify(sig)
- end
-end
+ def rsavp1(key, sig)
+ key.verify(sig)
+ end
+ end
-# 6 Overview of schemes
+ # 6 Overview of schemes
-# 7 Encryption schemes
-module EncryptionScheme
-module_function
-
- def rsaes_oaep_encrypt(key, msg, seed = nil, label = '')
- RSAESOAEP.new.encrypt(key, msg, seed, label)
- end
+ # 7 Encryption schemes
+ module EncryptionScheme
+ module_function
- def rsaes_oaep_decrypt(key, cipher, seed = nil, label = '')
- RSAESOAEP.new.decrypt(key, cipher, seed, label)
- end
+ def rsaes_oaep_encrypt(key, msg, seed = nil, label = '')
+ RSAESOAEP.new.encrypt(key, msg, seed, label)
+ end
+ def rsaes_oaep_decrypt(key, cipher, seed = nil, label = '')
+ RSAESOAEP.new.decrypt(key, cipher, seed, label)
+ end
- class RSAESOAEP
- include DataConversion
- include CryptographicPrimitive
- def initialize(digest = Digest::SHA1)
- @hlen = Hash.size(digest)
- @encryption_encoder = EncryptionEncoding::EMEOAEP.new(digest)
- end
+ class RSAESOAEP
+ include DataConversion
+ include CryptographicPrimitive
- def encrypt(key, msg, seed = nil, label = '')
- k = key.modbytes
- if msg.size > k - 2 * @hlen - 2
- raise ArgumentError, "message too long"
- end
- em = @encryption_encoder.encode(msg, k, seed, label)
- m = os2ip(em)
- c = rsaep(key, m)
- i2osp(c, k)
- end
+ def initialize(digest = Digest::SHA1)
+ @hlen = Hash.size(digest)
+ @encryption_encoder = EncryptionEncoding::EMEOAEP.new(digest)
+ end
- def decrypt(key, cipher, label = '')
- k = key.modbytes
- if cipher.size != k
- raise ArgumentError, "decryption error"
- end
- if k < 2 * @hlen + 2
- raise ArgumentError, "decryption error"
- end
- c = os2ip(cipher)
- m = rsadp(key, c)
- em = i2osp(m, k)
- @encryption_encoder.decode(em, k, label)
+ def encrypt(key, msg, seed = nil, label = '')
+ k = key.modbytes
+ if msg.size > k - 2 * @hlen - 2
+ raise ArgumentError, "message too long"
+ end
+ em = @encryption_encoder.encode(msg, k, seed, label)
+ m = os2ip(em)
+ c = rsaep(key, m)
+ i2osp(c, k)
+ end
+
+ def decrypt(key, cipher, label = '')
+ k = key.modbytes
+ if cipher.size != k
+ raise ArgumentError, "decryption error"
+ end
+ if k < 2 * @hlen + 2
+ raise ArgumentError, "decryption error"
+ end
+ c = os2ip(cipher)
+ m = rsadp(key, c)
+ em = i2osp(m, k)
+ @encryption_encoder.decode(em, k, label)
+ end
+ end
end
- end
-end
-# 7.1.1 1.b and 7.1.2 3 Encoding methods for encryption
-module EncryptionEncoding
-module_function
+ # 7.1.1 1.b and 7.1.2 3 Encoding methods for encryption
+ module EncryptionEncoding
+ module_function
- def eme_oaep_encode(msg, embits, seed = nil)
- EMEOAEP.new.encode(msg, embits, seed)
- end
+ def eme_oaep_encode(msg, embits, seed = nil)
+ EMEOAEP.new.encode(msg, embits, seed)
+ end
- def eme_oaep_decode(msg, em, embits)
- EMEOAEP.new.decode(msg, em, embits)
- end
+ def eme_oaep_decode(msg, em, embits)
+ EMEOAEP.new.decode(msg, em, embits)
+ end
- class EMEOAEP
- include Util
+ class EMEOAEP
+ include Util
- def initialize(digest = Digest::SHA1, mgf = nil)
- @digest = digest
- @hlen = Hash.size(@digest)
- @mgf = mgf || MaskGeneration::MGF1.new(@digest)
- end
+ def initialize(digest = Digest::SHA1, mgf = nil)
+ @digest = digest
+ @hlen = Hash.size(@digest)
+ @mgf = mgf || MaskGeneration::MGF1.new(@digest)
+ end
- def encode(msg, embytes, seed = nil, label = '')
- lhash = dohash(label)
- ps = "\x00" * (embytes - msg.size - 2 * @hlen - 2)
- db = lhash + ps + "\x01" + msg
- seed ||= OpenSSL::Random.random_bytes(@hlen)
- dbmask = @mgf.generate(seed, embytes - @hlen - 1)
- maskeddb = xor(db, dbmask)
- seedmask = @mgf.generate(maskeddb, @hlen)
- maskedseed = xor(seed, seedmask)
+ def encode(msg, embytes, seed = nil, label = '')
+ lhash = dohash(label)
+ ps = "\x00" * (embytes - msg.size - 2 * @hlen - 2)
+ db = lhash + ps + "\x01" + msg
+ seed ||= OpenSSL::Random.random_bytes(@hlen)
+ dbmask = @mgf.generate(seed, embytes - @hlen - 1)
+ maskeddb = xor(db, dbmask)
+ seedmask = @mgf.generate(maskeddb, @hlen)
+ maskedseed = xor(seed, seedmask)
"\x00" + maskedseed + maskeddb
- end
+ end
- def decode(em, embytes, label = '')
- lhash = dohash(label)
- y = em[0]
- maskedseed = em[1, @hlen]
- maskeddb = em[1 + @hlen, embytes - @hlen - 1]
- seedmask = @mgf.generate(maskeddb, @hlen)
- seed = xor(maskedseed, seedmask)
- dbmask = @mgf.generate(seed, embytes - @hlen - 1)
- db = xor(maskeddb, dbmask)
- lhashdash = db[0, @hlen]
- if lhashdash != lhash
- raise ArgumentError, "decryption error"
- end
- psm = db[@hlen, embytes - 2 * @hlen - 1]
- if /\A(\x00*)\x01([\x00-\xff]*)\z/ =~ psm
- ps, m = $1, $2
- else
- raise ArgumentError, "decryption error"
- end
- m
- end
+ def decode(em, embytes, label = '')
+ lhash = dohash(label)
+ y = em[0]
+ maskedseed = em[1, @hlen]
+ maskeddb = em[1 + @hlen, embytes - @hlen - 1]
+ seedmask = @mgf.generate(maskeddb, @hlen)
+ seed = xor(maskedseed, seedmask)
+ dbmask = @mgf.generate(seed, embytes - @hlen - 1)
+ db = xor(maskeddb, dbmask)
+ lhashdash = db[0, @hlen]
+ if lhashdash != lhash
+ raise ArgumentError, "decryption error"
+ end
+ psm = db[@hlen, embytes - 2 * @hlen - 1]
+ if /\A(\x00*)\x01([\x00-\xff]*)\z/ =~ psm
+ ps, m = $1, $2
+ else
+ raise ArgumentError, "decryption error"
+ end
+ m
+ end
- private
+ private
- def dohash(msg)
- @digest.digest(msg)
+ def dohash(msg)
+ @digest.digest(msg)
+ end
+ end
end
- end
-end
-# 8 Signature schemes
-module SignatureScheme
-module_function
+ # 8 Signature schemes
+ module SignatureScheme
+ module_function
- def rsassa_pss_sign(key, msg)
- RSASSAPSS.new.sign(key, msg)
- end
+ def rsassa_pss_sign(key, msg)
+ RSASSAPSS.new.sign(key, msg)
+ end
- def rsassa_pss_verify(key, msg, sig)
- RSASSAPSS.new.verify(key, msg, sig)
- end
+ def rsassa_pss_verify(key, msg, sig)
+ RSASSAPSS.new.verify(key, msg, sig)
+ end
- def rsassa_pss_sign_hash(key, hash)
- RSASSAPSS.new.sign_hash(key, hash)
- end
+ def rsassa_pss_sign_hash(key, hash)
+ RSASSAPSS.new.sign_hash(key, hash)
+ end
- def rsassa_pss_verify_hash(key, hash, sig)
- RSASSAPSS.new.verify_hash(key, hash, sig)
- end
+ def rsassa_pss_verify_hash(key, hash, sig)
+ RSASSAPSS.new.verify_hash(key, hash, sig)
+ end
- def rsassa_pkcs1v1_5_sign(key, msg)
- RSASSAPKCS1v1_5.new.sign(key, msg)
- end
+ def rsassa_pkcs1v1_5_sign(key, msg)
+ RSASSAPKCS1v1_5.new.sign(key, msg)
+ end
- def rsassa_pkcs1v1_5_verify(key, msg, sig)
- RSASSAPKCS1v1_5.new.verify(key, msg, sig)
- end
+ def rsassa_pkcs1v1_5_verify(key, msg, sig)
+ RSASSAPKCS1v1_5.new.verify(key, msg, sig)
+ end
- def rsassa_pkcs1v1_5_sign_hash(key, hash)
- RSASSAPKCS1v1_5.new.sign_hash(key, hash)
- end
+ def rsassa_pkcs1v1_5_sign_hash(key, hash)
+ RSASSAPKCS1v1_5.new.sign_hash(key, hash)
+ end
- def rsassa_pkcs1v1_5_verify_hash(key, hash, sig)
- RSASSAPKCS1v1_5.new.verify_hash(key, hash, sig)
- end
+ def rsassa_pkcs1v1_5_verify_hash(key, hash, sig)
+ RSASSAPKCS1v1_5.new.verify_hash(key, hash, sig)
+ end
- class RSASSAPSS
- include Util
- include DataConversion
- include CryptographicPrimitive
+ class RSASSAPSS
+ include Util
+ include DataConversion
+ include CryptographicPrimitive
- def initialize(digest = Digest::SHA1, slen = 20, mgf = nil)
- @signature_encoder = SignatureEncoding::EMSAPSS.new(digest, slen, mgf)
- end
+ def initialize(digest = Digest::SHA1, slen = 20, mgf = nil)
+ @signature_encoder = SignatureEncoding::EMSAPSS.new(digest, slen, mgf)
+ end
- def sign(key, msg, salt = nil)
- modbits = key.modbits
- em = @signature_encoder.encode(msg, modbits - 1, salt)
- sign_em(key, em, modbits)
- end
+ def sign(key, msg, salt = nil)
+ modbits = key.modbits
+ em = @signature_encoder.encode(msg, modbits - 1, salt)
+ sign_em(key, em, modbits)
+ end
- def sign_hash(key, hash, salt = nil)
- modbits = key.modbits
- em = @signature_encoder.encode_hash(hash, modbits - 1, salt)
- sign_em(key, em, modbits)
- end
+ def sign_hash(key, hash, salt = nil)
+ modbits = key.modbits
+ em = @signature_encoder.encode_hash(hash, modbits - 1, salt)
+ sign_em(key, em, modbits)
+ end
- def verify(key, msg, sig)
- modbits = key.modbits
- em = decode_em(key, sig, modbits)
- @signature_encoder.verify(msg, em, modbits - 1)
- end
+ def verify(key, msg, sig)
+ modbits = key.modbits
+ em = decode_em(key, sig, modbits)
+ @signature_encoder.verify(msg, em, modbits - 1)
+ end
- def verify_hash(key, hash, sig)
- modbits = key.modbits
- em = decode_em(key, sig, modbits)
- @signature_encoder.verify_hash(hash, em, modbits - 1)
- end
+ def verify_hash(key, hash, sig)
+ modbits = key.modbits
+ em = decode_em(key, sig, modbits)
+ @signature_encoder.verify_hash(hash, em, modbits - 1)
+ end
- private
+ private
- def sign_em(key, em, modbits)
- m = os2ip(em)
- s = rsasp1(key, m)
- s = i2osp(s, divceil(modbits, 8))
- s
- end
+ def sign_em(key, em, modbits)
+ m = os2ip(em)
+ s = rsasp1(key, m)
+ s = i2osp(s, divceil(modbits, 8))
+ s
+ end
- def decode_em(key, sig, modbits)
- if sig.size != divceil(modbits - 1, 8)
- raise ArgumentError, "invalid signature"
- end
- s = os2ip(sig)
- m = rsavp1(key, s)
- emlen = divceil(modbits - 1, 8)
- i2osp(m, emlen)
- end
- end
+ def decode_em(key, sig, modbits)
+ if sig.size != divceil(modbits - 1, 8)
+ raise ArgumentError, "invalid signature"
+ end
+ s = os2ip(sig)
+ m = rsavp1(key, s)
+ emlen = divceil(modbits - 1, 8)
+ i2osp(m, emlen)
+ end
+ end
- class RSASSAPKCS1v1_5
- include DataConversion
- include CryptographicPrimitive
+ class RSASSAPKCS1v1_5
+ include DataConversion
+ include CryptographicPrimitive
- def initialize(digest = Digest::SHA1)
- @signature_encoder = SignatureEncoding::EMSAPKCS1v1_5.new(digest)
- end
+ def initialize(digest = Digest::SHA1)
+ @signature_encoder = SignatureEncoding::EMSAPKCS1v1_5.new(digest)
+ end
- def sign(key, msg)
- k = key.modbytes
- em = @signature_encoder.encode(msg, k)
- sign_em(key, em, k)
- end
+ def sign(key, msg)
+ k = key.modbytes
+ em = @signature_encoder.encode(msg, k)
+ sign_em(key, em, k)
+ end
- def sign_hash(key, hash)
- k = key.modbytes
- em = @signature_encoder.encode_hash(hash, k)
- sign_em(key, em, k)
- end
+ def sign_hash(key, hash)
+ k = key.modbytes
+ em = @signature_encoder.encode_hash(hash, k)
+ sign_em(key, em, k)
+ end
- def verify(key, msg, sig)
- k = key.modbytes
- em = decode_em(key, sig, k)
- emdash = @signature_encoder.encode(msg, k)
- unless em == emdash
- raise ArgumentError, "invalid signature"
- end
- true
- end
+ def verify(key, msg, sig)
+ k = key.modbytes
+ em = decode_em(key, sig, k)
+ emdash = @signature_encoder.encode(msg, k)
+ unless em == emdash
+ raise ArgumentError, "invalid signature"
+ end
+ true
+ end
- def verify_hash(key, hash, sig)
- k = key.modbytes
- em = decode_em(key, sig, k)
- emdash = @signature_encoder.encode_hash(hash, k)
- unless em == emdash
- raise ArgumentError, "invalid signature"
- end
- true
- end
+ def verify_hash(key, hash, sig)
+ k = key.modbytes
+ em = decode_em(key, sig, k)
+ emdash = @signature_encoder.encode_hash(hash, k)
+ unless em == emdash
+ raise ArgumentError, "invalid signature"
+ end
+ true
+ end
- private
+ private
- def sign_em(key, em, k)
- m = os2ip(em)
- s = rsasp1(key, m)
- i2osp(s, k)
- end
+ def sign_em(key, em, k)
+ m = os2ip(em)
+ s = rsasp1(key, m)
+ i2osp(s, k)
+ end
- def decode_em(key, sig, k)
- if sig.size != k
- raise ArgumentError, "invalid signature"
- end
- s = os2ip(sig)
- m = rsavp1(key, s)
- i2osp(m, k)
+ def decode_em(key, sig, k)
+ if sig.size != k
+ raise ArgumentError, "invalid signature"
+ end
+ s = os2ip(sig)
+ m = rsavp1(key, s)
+ i2osp(m, k)
+ end
+ end
end
- end
-end
-# 9 Encoding methods for signatures with appendix
-module SignatureEncoding
-module_function
+ # 9 Encoding methods for signatures with appendix
+ module SignatureEncoding
+ module_function
- def emsa_pss_encode(msg, embits, salt = nil)
- EMSAPSS.new.encode(msg, embits, salt)
- end
+ def emsa_pss_encode(msg, embits, salt = nil)
+ EMSAPSS.new.encode(msg, embits, salt)
+ end
- def emsa_pss_verify(msg, em, embits)
- EMSAPSS.new.verify(msg, em, embits)
- end
+ def emsa_pss_verify(msg, em, embits)
+ EMSAPSS.new.verify(msg, em, embits)
+ end
- def emsa_pkcs1_v1_5_encode(msg, emlen)
- EMSAPKCS1v1_5.new.encode(msg, emlen)
- end
+ def emsa_pkcs1_v1_5_encode(msg, emlen)
+ EMSAPKCS1v1_5.new.encode(msg, emlen)
+ end
- class EMSAPSS
- include Util
+ class EMSAPSS
+ include Util
- def initialize(digest = Digest::SHA1, slen = 20, mgf = nil)
- @digest = digest
- @slen = slen
- @hlen = Hash.size(@digest)
- @mgf = mgf || MaskGeneration::MGF1.new(@digest)
- end
+ def initialize(digest = Digest::SHA1, slen = 20, mgf = nil)
+ @digest = digest
+ @slen = slen
+ @hlen = Hash.size(@digest)
+ @mgf = mgf || MaskGeneration::MGF1.new(@digest)
+ end
- def encode(msg, embits, salt = nil)
- mhash = dohash(msg)
- encode_hash(mhash, embits, salt)
- end
+ def encode(msg, embits, salt = nil)
+ mhash = dohash(msg)
+ encode_hash(mhash, embits, salt)
+ end
- def encode_hash(mhash, embits, salt = nil)
- emlen = divceil(embits, 8)
- if emlen < @hlen + @slen + 2
- raise ArgumentError, "encoding error"
- end
- salt ||= OpenSSL::Random.random_bytes(@slen)
- mdash = "\x00" * 8 + mhash + salt
- h = dohash(mdash)
- ps = "\x00" * (emlen - @slen - @hlen - 2)
- db = ps + "\x01" + salt
- dbmask = @mgf.generate(h, emlen - @hlen - 1)
- maskeddb = xor(db, dbmask)
- maskeddb[0] &= (0xff >> (8 * emlen - embits))
- p [emlen, embits, (0xff >> (8 * emlen - embits))]
- em = maskeddb + h + "\xbc"
- em
- end
+ def encode_hash(mhash, embits, salt = nil)
+ emlen = divceil(embits, 8)
+ if emlen < @hlen + @slen + 2
+ raise ArgumentError, "encoding error"
+ end
+ salt ||= OpenSSL::Random.random_bytes(@slen)
+ mdash = "\x00" * 8 + mhash + salt
+ h = dohash(mdash)
+ ps = "\x00" * (emlen - @slen - @hlen - 2)
+ db = ps + "\x01" + salt
+ dbmask = @mgf.generate(h, emlen - @hlen - 1)
+ maskeddb = xor(db, dbmask)
+ maskeddb[0] &= (0xff >> (8 * emlen - embits))
+ #p [emlen, embits, (0xff >> (8 * emlen - embits))]
+ em = maskeddb + h + "\xbc"
+ em
+ end
- def verify(msg, em, embits)
- mhash = dohash(msg)
- verify_hash(mhash, em, embits)
- end
+ def verify(msg, em, embits)
+ mhash = dohash(msg)
+ verify_hash(mhash, em, embits)
+ end
- def verify_hash(mhash, em, embits)
- emlen = divceil(embits, 8)
- if emlen < @hlen + @slen + 2
- raise ArgumentError, "inconsistent"
- end
- if em[-1] != 0xbc
- raise ArgumentError, "inconsistent"
- end
- maskeddb = em[0, emlen - @hlen - 1]
- h = em[emlen - @hlen - 1, @hlen]
- if maskeddb[0] & (0xff >> (8 * emlen - embits)) != maskeddb[0]
- raise ArgumentError, "inconsistent"
- end
- dbmask = @mgf.generate(h, emlen - @hlen - 1)
- db = xor(maskeddb, dbmask)
- db[0] &= (0xff >> (8 * emlen - embits))
- if /\A\x00+\z/ !~ db[0, emlen - @hlen - @slen - 2]
- raise ArgumentError, "inconsistent"
- end
- if db[emlen - @hlen - @slen - 2] != 0x01
- raise ArgumentError, "inconsistent"
- end
- salt = db[db.size - @slen, @slen]
- mdash = "\x00" * 8 + mhash + salt
- hdash = dohash(mdash)
- if h != hdash
- raise ArgumentError, "inconsistent"
- end
- true
- end
+ def verify_hash(mhash, em, embits)
+ emlen = divceil(embits, 8)
+ if emlen < @hlen + @slen + 2
+ raise ArgumentError, "inconsistent"
+ end
+ if em[-1] != 0xbc
+ raise ArgumentError, "inconsistent"
+ end
+ maskeddb = em[0, emlen - @hlen - 1]
+ h = em[emlen - @hlen - 1, @hlen]
+ if maskeddb[0] & (0xff >> (8 * emlen - embits)) != maskeddb[0]
+ raise ArgumentError, "inconsistent"
+ end
+ dbmask = @mgf.generate(h, emlen - @hlen - 1)
+ db = xor(maskeddb, dbmask)
+ db[0] &= (0xff >> (8 * emlen - embits))
+ if /\A\x00+\z/ !~ db[0, emlen - @hlen - @slen - 2]
+ raise ArgumentError, "inconsistent"
+ end
+ if db[emlen - @hlen - @slen - 2] != 0x01
+ raise ArgumentError, "inconsistent"
+ end
+ salt = db[db.size - @slen, @slen]
+ mdash = "\x00" * 8 + mhash + salt
+ hdash = dohash(mdash)
+ if h != hdash
+ raise ArgumentError, "inconsistent"
+ end
+ true
+ end
- private
+ private
- def dohash(msg)
- @digest.digest(msg)
- end
- end
+ def dohash(msg)
+ @digest.digest(msg)
+ end
+ end
- class EMSAPKCS1v1_5
- def initialize(digest = Digest::SHA1)
- @digest = digest
- end
+ class EMSAPKCS1v1_5
+ def initialize(digest = Digest::SHA1)
+ @digest = digest
+ end
- def encode(msg, emlen)
- h = dohash(msg)
- encode_hash(h, emlen)
- end
+ def encode(msg, emlen)
+ h = dohash(msg)
+ encode_hash(h, emlen)
+ end
- def encode_hash(h, emlen)
- t = Hash.asnoid(@digest) + h
- if emlen < t.size + 11
- raise ArgumentError, "intended encoded message length too short"
- end
- ps = "\xff" * (emlen - t.size - 3)
+ def encode_hash(h, emlen)
+ t = Hash.asnoid(@digest) + h
+ if emlen < t.size + 11
+ raise ArgumentError, "intended encoded message length too short"
+ end
+ ps = "\xff" * (emlen - t.size - 3)
"\x00\x01" + ps + "\x00" + t
- end
+ end
- private
+ private
- def dohash(msg)
- @digest.digest(msg)
+ def dohash(msg)
+ @digest.digest(msg)
+ end
+ end
end
- end
-end
-# B.1 Hash functions
-module Hash
- ALGORITHMS = {
- # MD5: 1.2.840.113549.2.5
- Digest::MD5 => [16, [0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x00, 0x04, 0x10]],
- # SHA-1: 1.3.14.3.2.26
- Digest::SHA1 => [20, [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03,
- 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14]],
- # SHA256: 2.16.840.1.101.3.4.2.1
- Digest::SHA256 => [32, [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20]],
- # SHA384: 2.16.840.1.101.3.4.2.2
- Digest::SHA384 => [48, [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30]],
- # SHA512: 2.16.840.1.101.3.4.2.3
- Digest::SHA512 => [64, [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
- 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40]],
- }
+ # B.1 Hash functions
+ module Hash
+ ALGORITHMS = {
+ # MD5: 1.2.840.113549.2.5
+ Digest::MD5 => [16, [0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48,
+ 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x00, 0x04, 0x10]],
+ # SHA-1: 1.3.14.3.2.26
+ Digest::SHA1 => [20, [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03,
+ 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14]],
+ # SHA256: 2.16.840.1.101.3.4.2.1
+ Digest::SHA256 => [32, [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20]],
+ # SHA384: 2.16.840.1.101.3.4.2.2
+ Digest::SHA384 => [48, [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30]],
+ # SHA512: 2.16.840.1.101.3.4.2.3
+ Digest::SHA512 => [64, [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40]],
+ }
-module_function
+ module_function
- def asnoid(digest)
- unless ALGORITHMS.key?(digest)
- raise ArgumentError, "unknown digest: #{digest}"
- end
- ALGORITHMS[digest][1].pack("c*")
- end
+ def asnoid(digest)
+ unless ALGORITHMS.key?(digest)
+ raise ArgumentError, "unknown digest: #{digest}"
+ end
+ ALGORITHMS[digest][1].pack("c*")
+ end
- def size(digest)
- unless ALGORITHMS.key?(digest)
- raise ArgumentError, "unknown digest: #{digest}"
+ def size(digest)
+ unless ALGORITHMS.key?(digest)
+ raise ArgumentError, "unknown digest: #{digest}"
+ end
+ ALGORITHMS[digest][0]
+ end
end
- ALGORITHMS[digest][0]
- end
-end
-# B.2 Mask generation functions
-module MaskGeneration
-module_function
+ # B.2 Mask generation functions
+ module MaskGeneration
+ module_function
- def mgf1(seed, masklen)
- MGF1.new.generate(seed, masklen)
- end
+ def mgf1(seed, masklen)
+ MGF1.new.generate(seed, masklen)
+ end
- class MGF1
- include Util
- include DataConversion
+ class MGF1
+ include Util
+ include DataConversion
- def initialize(digest = Digest::SHA1)
- @digest = digest
- @hlen = Hash.size(@digest)
- end
+ def initialize(digest = Digest::SHA1)
+ @digest = digest
+ @hlen = Hash.size(@digest)
+ end
- def generate(seed, masklen)
- if masklen > (2 << 31) * @hlen
- raise ArgumentError, "mask too long"
- end
- t = ""
- divceil(masklen, @hlen).times do |counter|
- t += dohash(seed + i2osp(counter, 4))
- end
- t[0, masklen]
- end
+ def generate(seed, masklen)
+ if masklen > (2 << 31) * @hlen
+ raise ArgumentError, "mask too long"
+ end
+ t = ""
+ divceil(masklen, @hlen).times do |counter|
+ t += dohash(seed + i2osp(counter, 4))
+ end
+ t[0, masklen]
+ end
- private
+ private
- def dohash(msg)
- @digest.digest(msg)
+ def dohash(msg)
+ @digest.digest(msg)
+ end
+ end
end
- end
-end
-
end
-
-=begin
-if $0 == __FILE__
- #pkeyfile = ARGV.shift or raise "pkey file not given"
-
- osslkey = OpenSSL::PKey::RSA.new(1024)
-
- n = osslkey.n.to_i
- e = osslkey.e.to_i
- d = osslkey.d.to_i
- p = osslkey.p.to_i
- q = osslkey.q.to_i
- dp = osslkey.dmp1.to_i
- dq = osslkey.dmq1.to_i
- qinv = osslkey.iqmp.to_i
-
-require 'hexdump'
-require 'base64'
- rsapss = PKCS1::SignatureScheme::RSASSAPSS.new(Digest::SHA256, 0, PKCS1::MaskGeneration::MGF1.new(Digest::SHA1))
- key = PKCS1::Key::RSA.new(n, e, d)
-# {{{
-# key2 = PKCS1::Key::RSACRTPrivateKey.new(n, d, p, q, dp, dq, qinv)
-# puts PGP::HexDump.encode(rsapss.sign_hash(key2, "hello world", "\0"*8))
-
- #p Base64::b64encode PKCS1::DataConversion.i2osp(65537, 3)
- #puts "-"*100
- #p PKCS1::DataConversion.os2ip(PKCS1::DataConversion.i2osp(65537, 3))
-# }}}
- key = PKCS1::Key::RSA.new(osslkey.n.to_i, osslkey.e.to_i, osslkey.d.to_i)
- msg = "hello"
- #p PKCS1::DataConversion.i2osp(PKCS1::CryptographicPrimitive.rsadp(key, PKCS1::CryptographicPrimitive.rsaep(key, PKCS1::DataConversion.os2ip(msg))), msg.size)# {{{
- #p PKCS1::DataConversion.i2osp(PKCS1::CryptographicPrimitive.rsavp1(key, PKCS1::CryptographicPrimitive.rsasp1(key, PKCS1::DataConversion.os2ip(msg))), msg.size)
-
- #p PKCS1::MaskGeneration.mgf1("abc", 20)
- #p PKCS1::MaskGeneration.mgf1("abcd", 20)
-# }}}
- pss = PKCS1::SignatureEncoding::EMSAPSS.new(Digest::SHA1, 8)
- #p pss.encode("hello", 1023)# {{{
- #p pss.verify("hello", pss.encode("hello", 1023), 1023)
-
- #rsapss = PKCS1::SignatureScheme::RSASSAPSS.new(Digest::SHA1, 0)
- #p rsapss.sign(key, "hello")
- #p rsapss.verify(key, "hello", rsapss.sign(key, "hello"))
-# }}}
- msg = "foo\nbar" * 1024
- hash = Digest::SHA1.digest(msg)
- #p rsapss.verify_hash(key, hash, rsapss.sign_hash(key, hash))# {{{
- #p rsapss.verify(key, msg, rsapss.sign_hash(key, hash))
- #p rsapss.verify_hash(key, hash, rsapss.sign(key, msg))
-
- #p Base64::b64encode PKCS1::SignatureEncoding.emsa_pkcs1_v1_5_encode("foo", 128)# }}}
- puts "-"*100
- rsapkcs1 = PKCS1::SignatureScheme::RSASSAPKCS1v1_5.new(Digest::SHA1)
- p Base64::b64encode rsapkcs1.sign(key, "hello")
- puts "-"*100# {{{
- #p Base64::b64encode rsapkcs1.verify(key, "hello", rsapkcs1.sign(key, "hello"))
- puts "-"*100
- #p Base64::b64encode osslkey.sign(OpenSSL::Digest::SHA1.new, "hello")
- puts "-"*100
- #p Base64::b64encode osslkey.verify(OpenSSL::Digest::SHA1.new, rsapkcs1.sign(key, "hello"), "hello")
-# }}}
- rsaoaep = PKCS1::EncryptionScheme::RSAESOAEP.new(Digest::SHA1)
- msg = "hello"
-# p rsaoaep.encrypt(key, msg)
-# p Base64::b64encode osslkey.public_encrypt(msg, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
- puts "-"*100# {{{
- #p osslkey.private_decrypt(rsaoaep.encrypt(key, msg), OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) == msg
- #puts "-"*100
- #p rsaoaep.decrypt(key, rsaoaep.encrypt(key, msg)) == msg# }}}
-end
-=end
Modified: topf/trunk/lib/topf.rb
===================================================================
--- topf/trunk/lib/topf.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/lib/topf.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -11,6 +11,7 @@
require "fuzz-struct"
require "fuzz"
+require "gdb"
require "dir"
require "control"
Modified: topf/trunk/tor-control-fuzz.rb
===================================================================
--- topf/trunk/tor-control-fuzz.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/tor-control-fuzz.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,7 +1,9 @@
require "lib/topf"
begin
- observer = Fuzz::BinaryObserver.new "tor", "-f stuff/torrc", "&> /dev/null"
+ config = YAML::load_file "config/config.yml"
+
+ observer = Fuzz::BinaryObserver.new "#{config["BINDIR"]}/tor", config["COREDIR"], "-f #{config["CONFDIR"]}/torrc", "&> /dev/null"
observer.observe!
sleep 2
@@ -15,14 +17,14 @@
Fuzz::LOGGER.info "[x] loading options"
- config = YAML::load_file "config/config.yml"
options = {
:host => config["HOST"],
:port => config["CONTROLPORT"],
:debug => config["DEBUG"],
:type => :tcp,
- :timeout => 0.01,
+ #:timeout => 0.01,
+ :timeout => 0.5,
:observer => observer
}
@@ -60,7 +62,7 @@
rescue Exception => error
#Fuzz::LOGGER.info "[x] %s\n%s\nclosing everything down" % [ $!, error.backtrace.join("\n") ]
- Fuzz::LOGGER.info "[x] %s\nclosing everything down" % [ $! ]
+ Fuzz::LOGGER.info "[x] closing everything down"
fuzzer.close if fuzzer
observer.exit if observer and started
end
Modified: topf/trunk/tor-dir-fuzz.rb
===================================================================
--- topf/trunk/tor-dir-fuzz.rb 2007-08-20 10:10:09 UTC (rev 11213)
+++ topf/trunk/tor-dir-fuzz.rb 2007-08-20 11:09:04 UTC (rev 11214)
@@ -1,17 +1,15 @@
require "lib/topf"
begin
- observer = Fuzz::BinaryObserver.new "tor", "-f torrc", "&> /dev/null"
+ config = YAML::load_file "config/config.yml"
+
+ observer = Fuzz::BinaryObserver.new "#{config["BINDIR"]}/tor", config["COREDIR"], "-f #{config["CONFDIR"]}/torrc", "&> /dev/null"
observer.observe!
sleep 2
-
- config = YAML::load_file "config.yml"
+ Fuzz::LOGGER.info "[x] tor pid: %d" % observer.get_pid
- rd = TOPF::Dir::RouterDescriptor.new( config["KEYFILE"])
-
options = {
- :object => rd,
:host => config["HOST"],
:port => config["DIRPORT"],
:type => :http,
@@ -20,8 +18,76 @@
:debug => config["DEBUG"]
}
- fuzzer = Fuzz::Connection.new( options )
- fuzzer.fuzz!
+ osslkey = OpenSSL::PKey::RSA.new(1024)
+ pkcs1 = PKCS1::SignatureScheme::RSASSAPKCS1v1_5.new(Digest::SHA1)
+ key = PKCS1::Key::RSA.new(osslkey.n.to_i , osslkey.e.to_i, osslkey.d.to_i)
+
+
+ TOPF::Dir::ROUTERDESCRIPTOR = Fuzz::Collection.new("\n")
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::RouterItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::PlatformItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::PublishedItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::FingerprintItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::UptimeItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::BandwidthItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::OnionKeyItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::SigningKeyItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::WriteHistoryItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::ReadHistoryItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::ContactItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_struct TOPF::Dir::RejectItem.new
+ TOPF::Dir::ROUTERDESCRIPTOR.add_tests Fuzz::DEFAULT_TESTS
+
+ TOPF::Dir::ROUTERDESCRIPTOR.add_format_block{|args, structs, join_char|
+ resultString = []
+ structs.each_with_index do |struct, index|
+ if index == args[:fuzz_index]
+ begin
+ data = struct.fuzz!.join(" ")
+ resultString.push data
+ rescue Exception => exception
+ Fuzz::LOGGER.info "[x] fuzzing #{struct.class}"
+ args[:fuzz_index] += 1
+ end
+ else
+ resultString.push struct.output(" ")
+ end
+ end
+ resultString = resultString.join(join_char)
+
+ resultString << "\nrouter-signature\n"
+ #sig = Base64::b64encode( args[:pkcs1].sign(args[:key], resultString) )
+ #sig = Base64::b64encode( Digest::SHA1.hexdigest( args[:pkcs1].sign(args[:key], resultString) ) )
+ #sig = Base64::b64encode( PKCS1::SignatureScheme::RSASSAPSS.new.sign(args[:key], resultString) )
+ #sig = Base64::b64encode( PKCS1::SignatureScheme::RSASSAPKCS1v1_5.new.sign(args[:key], resultString) )
+ sig = ""
+
+ resultString << "-----BEGIN SIGNATURE-----\n"
+ resultString << sig
+ resultString << "-----END SIGNATURE-----" << "\n"*2
+ [ resultString, args[:fuzz_index] ]
+ }
+
+ fuzzer = Fuzz::Connection.new( options )
+
+ actual_number = 0
+ number_of_tests = TOPF::Dir::ROUTERDESCRIPTOR.number_of_tests
+
+ Thread.new do
+ while true
+ sleep 10
+ actual = number_of_tests-actual_number
+ Fuzz::LOGGER.info "[i] %d%% %d/%d tests done" % [ actual/(number_of_tests/100.0), actual, number_of_tests ]
+ end
+ end
+
+ while true
+ data, actual_number = TOPF::Dir::ROUTERDESCRIPTOR.fuzz!( {:pkcs1 => pkcs1, :key => key , :osslkey => osslkey} )
+ response, body = fuzzer.send data
+ end
+
+rescue Exception => exception
+ Fuzz::LOGGER.info "[x] %s\n%s\nclosing everything down" % [ $!, exception.backtrace.join("\n") ]
fuzzer.close
observer.exit
end
More information about the tor-commits
mailing list