Newer
Older
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
doing a RAND_seed() on the value returned from a stat() system call
on the file and if 'number' is non-zero, upto 'number' bytes read
from the file. The number of bytes passed to RAND_seed() is returned.
int RAND_write_file(
char *file),
RAND_write_file() writes N random bytes to the file 'file', where
N is the size of the internal RND state (currently 1k).
This is a suitable method of saving RNG state for reloading via
RAND_load_file().
What follows is a description of this RNG and a description of the rational
behind it's design.
It should be noted that this RNG is intended to be used to generate
'random' keys for various ciphers including generation of DH and RSA keys.
It should also be noted that I have just created a system that I am happy with.
It may be overkill but that does not worry me. I have not spent that much
time on this algorithm so if there are glaring errors, please let me know.
Speed has not been a consideration in the design of these routines.
First up I will state the things I believe I need for a good RNG.
1) A good hashing algorithm to mix things up and to convert the RNG 'state'
to random numbers.
2) An initial source of random 'state'.
3) The state should be very large. If the RNG is being used to generate
4096 bit RSA keys, 2 2048 bit random strings are required (at a minimum).
If your RNG state only has 128 bits, you are obviously limiting the
search space to 128 bits, not 2048. I'm probably getting a little
carried away on this last point but it does indicate that it may not be
a bad idea to keep quite a lot of RNG state. It should be easier to
break a cipher than guess the RNG seed data.
4) Any RNG seed data should influence all subsequent random numbers
generated. This implies that any random seed data entered will have
an influence on all subsequent random numbers generated.
5) When using data to seed the RNG state, the data used should not be
extractable from the RNG state. I believe this should be a
requirement because one possible source of 'secret' semi random
data would be a private key or a password. This data must
not be disclosed by either subsequent random numbers or a
'core' dump left by a program crash.
6) Given the same initial 'state', 2 systems should deviate in their RNG state
(and hence the random numbers generated) over time if at all possible.
7) Given the random number output stream, it should not be possible to determine
the RNG state or the next random number.
The algorithm is as follows.
There is global state made up of a 1023 byte buffer (the 'state'), a
working message digest ('md') and a counter ('count').
Whenever seed data is added, it is inserted into the 'state' as
follows.
The input is chopped up into units of 16 bytes (or less for
the last block). Each of these blocks is run through the MD5
message digest. The data passed to the MD5 digest is the
current 'md', the same number of bytes from the 'state'
(the location determined by in incremented looping index) as
the current 'block' and the new key data 'block'. The result
of this is kept in 'md' and also xored into the 'state' at the
same locations that were used as input into the MD5.
I believe this system addresses points 1 (MD5), 3 (the 'state'),
4 (via the 'md'), 5 (by the use of MD5 and xor).
When bytes are extracted from the RNG, the following process is used.
For each group of 8 bytes (or less), we do the following,
Input into MD5, the top 8 bytes from 'md', the byte that are
to be overwritten by the random bytes and bytes from the
'state' (incrementing looping index). From this digest output
(which is kept in 'md'), the top (upto) 8 bytes are
returned to the caller and the bottom (upto) 8 bytes are xored
into the 'state'.
Finally, after we have finished 'generation' random bytes for the
called, 'count' (which is incremented) and 'md' are fed into MD5 and
the results are kept in 'md'.
I believe the above addressed points 1 (use of MD5), 6 (by
hashing into the 'state' the 'old' data from the caller that
is about to be overwritten) and 7 (by not using the 8 bytes
given to the caller to update the 'state', but they are used
to update 'md').
So of the points raised, only 2 is not addressed, but sources of
random data will always be a problem.
==== rc2.doc ========================================================
The RC2 library.
RC2 is a block cipher that operates on 64bit (8 byte) quantities. It
uses variable size key, but 128bit (16 byte) key would normally be considered
good. It can be used in all the modes that DES can be used. This
library implements the ecb, cbc, cfb64, ofb64 modes.
I have implemented this library from an article posted to sci.crypt on
11-Feb-1996. I personally don't know how far to trust the RC2 cipher.
While it is capable of having a key of any size, not much reseach has
publically been done on it at this point in time (Apr-1996)
since the cipher has only been public for a few months :-)
It is of a similar speed to DES and IDEA, so unless it is required for
meeting some standard (SSLv2, perhaps S/MIME), it would probably be advisable
to stick to IDEA, or for the paranoid, Tripple DES.
Mind you, having said all that, I should mention that I just read alot and
implement ciphers, I'm a 'babe in the woods' when it comes to evaluating
ciphers :-).
For all calls that have an 'input' and 'output' variables, they can be the
same.
This library requires the inclusion of 'rc2.h'.
All of the encryption functions take what is called an RC2_KEY as an
argument. An RC2_KEY is an expanded form of the RC2 key.
For all modes of the RC2 algorithm, the RC2_KEY used for
decryption is the same one that was used for encryption.
The define RC2_ENCRYPT is passed to specify encryption for the functions
that require an encryption/decryption flag. RC2_DECRYPT is passed to
specify decryption.
Please note that any of the encryption modes specified in my DES library
could be used with RC2. I have only implemented ecb, cbc, cfb64 and
ofb64 for the following reasons.
- ecb is the basic RC2 encryption.
- cbc is the normal 'chaining' form for block ciphers.
- cfb64 can be used to encrypt single characters, therefore input and output
do not need to be a multiple of 8.
- ofb64 is similar to cfb64 but is more like a stream cipher, not as
secure (not cipher feedback) but it does not have an encrypt/decrypt mode.
- If you want triple RC2, thats 384 bits of key and you must be totally
obsessed with security. Still, if you want it, it is simple enough to
copy the function from the DES library and change the des_encrypt to
RC2_encrypt; an exercise left for the paranoid reader :-).
The functions are as follows:
void RC2_set_key(
RC2_KEY *ks;
int len;
unsigned char *key;
int bits;
RC2_set_key converts an 'len' byte key into a RC2_KEY.
A 'ks' is an expanded form of the 'key' which is used to
perform actual encryption. It can be regenerated from the RC2 key
so it only needs to be kept when encryption or decryption is about
to occur. Don't save or pass around RC2_KEY's since they
are CPU architecture dependent, 'key's are not. RC2 is an
interesting cipher in that it can be used with a variable length
key. 'len' is the length of 'key' to be used as the key.
A 'len' of 16 is recomended. The 'bits' argument is an
interesting addition which I only found out about in Aug 96.
BSAFE uses this parameter to 'limit' the number of bits used
for the key. To use the 'key' unmodified, set bits to 1024.
This is what old versions of my RC2 library did (SSLeay 0.6.3).
RSAs BSAFE library sets this parameter to be 128 if 128 bit
keys are being used. So to be compatable with BSAFE, set it
to 128, if you don't want to reduce RC2's key length, leave it
at 1024.
void RC2_encrypt(
unsigned long *data,
RC2_KEY *key,
int encrypt);
This is the RC2 encryption function that gets called by just about
every other RC2 routine in the library. You should not use this
function except to implement 'modes' of RC2. I say this because the
functions that call this routine do the conversion from 'char *' to
long, and this needs to be done to make sure 'non-aligned' memory
access do not occur.
Data is a pointer to 2 unsigned long's and key is the
RC2_KEY to use. Encryption or decryption is indicated by 'encrypt'.
which can have the values RC2_ENCRYPT or RC2_DECRYPT.
void RC2_ecb_encrypt(
unsigned char *in,
unsigned char *out,
RC2_KEY *key,
int encrypt);
This is the basic Electronic Code Book form of RC2 (in DES this
mode is called Electronic Code Book so I'm going to use the term
for rc2 as well.
Input is encrypted into output using the key represented by
key. Depending on the encrypt, encryption or
decryption occurs. Input is 8 bytes long and output is 8 bytes.
void RC2_cbc_encrypt(
unsigned char *in,
unsigned char *out,
long length,
RC2_KEY *ks,
unsigned char *ivec,
int encrypt);
This routine implements RC2 in Cipher Block Chaining mode.
Input, which should be a multiple of 8 bytes is encrypted
(or decrypted) to output which will also be a multiple of 8 bytes.
The number of bytes is in length (and from what I've said above,
should be a multiple of 8). If length is not a multiple of 8, bad
things will probably happen. ivec is the initialisation vector.
This function updates iv after each call so that it can be passed to
the next call to RC2_cbc_encrypt().
void RC2_cfb64_encrypt(
unsigned char *in,
unsigned char *out,
long length,
RC2_KEY *schedule,
unsigned char *ivec,
int *num,
int encrypt);
This is one of the more useful functions in this RC2 library, it
implements CFB mode of RC2 with 64bit feedback.
This allows you to encrypt an arbitrary number of bytes,
you do not require 8 byte padding. Each call to this
routine will encrypt the input bytes to output and then update ivec
and num. Num contains 'how far' we are though ivec.
'Encrypt' is used to indicate encryption or decryption.
CFB64 mode operates by using the cipher to generate a stream
of bytes which is used to encrypt the plain text.
The cipher text is then encrypted to generate the next 64 bits to
be xored (incrementally) with the next 64 bits of plain
text. As can be seen from this, to encrypt or decrypt,
the same 'cipher stream' needs to be generated but the way the next
block of data is gathered for encryption is different for
encryption and decryption.
void RC2_ofb64_encrypt(
unsigned char *in,
unsigned char *out,
long length,
RC2_KEY *schedule,
unsigned char *ivec,
int *num);
This functions implements OFB mode of RC2 with 64bit feedback.
This allows you to encrypt an arbitrary number of bytes,
you do not require 8 byte padding. Each call to this
routine will encrypt the input bytes to output and then update ivec
and num. Num contains 'how far' we are though ivec.
This is in effect a stream cipher, there is no encryption or
decryption mode.
For reading passwords, I suggest using des_read_pw_string() from my DES library.
To generate a password from a text string, I suggest using MD5 (or MD2) to
produce a 16 byte message digest that can then be passed directly to
RC2_set_key().
=====
For more information about the specific RC2 modes in this library
(ecb, cbc, cfb and ofb), read the section entitled 'Modes of DES' from the
documentation on my DES library. What is said about DES is directly
applicable for RC2.
==== rc4.doc ========================================================
The RC4 library.
RC4 is a stream cipher that operates on a byte stream. It can be used with
any length key but I would recommend normally using 16 bytes.
This library requires the inclusion of 'rc4.h'.
The RC4 encryption function takes what is called an RC4_KEY as an argument.
The RC4_KEY is generated by the RC4_set_key function from the key bytes.
RC4, being a stream cipher, does not have an encryption or decryption mode.
It produces a stream of bytes that the input stream is xor'ed against and
so decryption is just a case of 'encrypting' again with the same key.
I have only put in one 'mode' for RC4 which is the normal one. This means
there is no initialisation vector and there is no feedback of the cipher
text into the cipher. This implies that you should not ever use the
same key twice if you can help it. If you do, you leave yourself open to
known plain text attacks; if you know the plain text and
corresponding cipher text in one message, all messages that used the same
key can have the cipher text decoded for the corresponding positions in the
cipher stream.
The main positive feature of RC4 is that it is a very fast cipher; about 4
times faster that DES. This makes it ideally suited to protocols where the
key is randomly chosen, like SSL.
The functions are as follows:
void RC4_set_key(
RC4_KEY *key;
int len;
unsigned char *data);
This function initialises the RC4_KEY structure with the key passed
in 'data', which is 'len' bytes long. The key data can be any
length but 16 bytes seems to be a good number.
void RC4(
RC4_KEY *key;
unsigned long len;
unsigned char *in;
unsigned char *out);
Do the actual RC4 encryption/decryption. Using the 'key', 'len'
bytes are transformed from 'in' to 'out'. As mentioned above,
decryption is the operation as encryption.
==== ref.doc ========================================================
I have lots more references etc, and will update this list in the future,
30 Aug 1996 - eay
SSL The SSL Protocol - from Netscapes.
RC4 Newsgroups: sci.crypt
From: sterndark@netcom.com (David Sterndark)
Subject: RC4 Algorithm revealed.
Message-ID: <sternCvKL4B.Hyy@netcom.com>
RC2 Newsgroups: sci.crypt
From: pgut01@cs.auckland.ac.nz (Peter Gutmann)
Subject: Specification for Ron Rivests Cipher No.2
Message-ID: <4fk39f$f70@net.auckland.ac.nz>
MD2 RFC1319 The MD2 Message-Digest Algorithm
MD5 RFC1321 The MD5 Message-Digest Algorithm
X509 Certificates
RFC1421 Privacy Enhancement for Internet Electronic Mail: Part I
RFC1422 Privacy Enhancement for Internet Electronic Mail: Part II
RFC1423 Privacy Enhancement for Internet Electronic Mail: Part III
RFC1424 Privacy Enhancement for Internet Electronic Mail: Part IV
RSA and various standard encoding
PKCS#1 RSA Encryption Standard
PKCS#5 Password-Based Encryption Standard
PKCS#7 Cryptographic Message Syntax Standard
A Layman's Guide to a Subset of ASN.1, BER, and DER
An Overview of the PKCS Standards
Some Examples of the PKCS Standards
IDEA Chapter 3 The Block Cipher IDEA
RSA, prime number generation and bignum algorithms
Introduction To Algorithms,
Thomas Cormen, Charles Leiserson, Ronald Rivest,
Section 29 Arithmetic Circuits
Section 33 Number-Theoretic Algorithms
Fast Private Key algorithm
Fast Decipherment Algorithm for RSA Public-Key Cryptosystem
J.-J. Quisquater and C. Couvreur, Electronics Letters,
14th October 1982, Vol. 18 No. 21
Prime number generation and bignum algorithms.
PGP-2.3a
==== rsa.doc ========================================================
The RSA encryption and utility routines.
The RSA routines are built on top of a big number library (the BN library).
There are support routines in the X509 library for loading and manipulating
the various objects in the RSA library. When errors are returned, read
about the ERR library for how to access the error codes.
All RSA encryption is done according to the PKCS-1 standard which is
compatible with PEM and RSAref. This means that any values being encrypted
must be less than the size of the modulus in bytes, minus 10, bytes long.
This library uses RAND_bytes()() for it's random data, make sure to feed
RAND_seed() with lots of interesting and varied data before using these
routines.
The RSA library has one specific data type, the RSA structure.
It is composed of 8 BIGNUM variables (see the BN library for details) and
can hold either a private RSA key or a public RSA key.
Some RSA libraries have different structures for public and private keys, I
don't. For my libraries, a public key is determined by the fact that the
RSA->d value is NULL. These routines will operate on any size RSA keys.
While I'm sure 4096 bit keys are very very secure, they take a lot longer
to process that 1024 bit keys :-).
The function in the RSA library are as follows.
RSA *RSA_new();
This function creates a new RSA object. The sub-fields of the RSA
type are also malloced so you should always use this routine to
create RSA variables.
void RSA_free(
RSA *rsa);
This function 'frees' an RSA structure. This routine should always
be used to free the RSA structure since it will also 'free' any
sub-fields of the RSA type that need freeing.
int RSA_size(
RSA *rsa);
This function returns the size of the RSA modulus in bytes. Why do
I need this you may ask, well the reason is that when you encrypt
with RSA, the output string will be the size of the RSA modulus.
So the output for the RSA_encrypt and the input for the RSA_decrypt
routines need to be RSA_size() bytes long, because this is how many
bytes are expected.
For the following 4 RSA encryption routines, it should be noted that
RSA_private_decrypt() should be used on the output from
RSA_public_encrypt() and RSA_public_decrypt() should be used on
the output from RSA_private_encrypt().
int RSA_public_encrypt(
int from_len;
unsigned char *from
unsigned char *to
RSA *rsa);
This function implements RSA public encryption, the rsa variable
should be a public key (but can be a private key). 'from_len'
bytes taken from 'from' and encrypted and put into 'to'. 'to' needs
to be at least RSA_size(rsa) bytes long. The number of bytes
written into 'to' is returned. -1 is returned on an error. The
operation performed is
to = from^rsa->e mod rsa->n.
int RSA_private_encrypt(
int from_len;
unsigned char *from
unsigned char *to
RSA *rsa);
This function implements RSA private encryption, the rsa variable
should be a private key. 'from_len' bytes taken from
'from' and encrypted and put into 'to'. 'to' needs
to be at least RSA_size(rsa) bytes long. The number of bytes
written into 'to' is returned. -1 is returned on an error. The
operation performed is
to = from^rsa->d mod rsa->n.
int RSA_public_decrypt(
int from_len;
unsigned char *from
unsigned char *to
RSA *rsa);
This function implements RSA public decryption, the rsa variable
should be a public key (but can be a private key). 'from_len'
bytes are taken from 'from' and decrypted. The decrypted data is
put into 'to'. The number of bytes encrypted is returned. -1 is
returned to indicate an error. The operation performed is
to = from^rsa->e mod rsa->n.
int RSA_private_decrypt(
int from_len;
unsigned char *from
unsigned char *to
RSA *rsa);
This function implements RSA private decryption, the rsa variable
should be a private key. 'from_len' bytes are taken
from 'from' and decrypted. The decrypted data is
put into 'to'. The number of bytes encrypted is returned. -1 is
returned to indicate an error. The operation performed is
to = from^rsa->d mod rsa->n.
int RSA_mod_exp(
BIGNUM *n;
BIGNUM *p;
RSA *rsa);
Normally you will never use this routine.
This is really an internal function which is called by
RSA_private_encrypt() and RSA_private_decrypt(). It performs
n=n^p mod rsa->n except that it uses the 5 extra variables in the
RSA structure to make this more efficient.
RSA *RSA_generate_key(
int bits;
unsigned long e;
void (*callback)();
char *cb_arg;
This routine is used to generate RSA private keys. It takes
quite a period of time to run and should only be used to
generate initial private keys that should then be stored
for later use. The passed callback function
will be called periodically so that feedback can be given
as to how this function is progressing.
'bits' is the length desired for the modulus, so it would be 1024
to generate a 1024 bit private key.
'e' is the value to use for the public exponent 'e'. Traditionally
it is set to either 3 or 0x10001.
The callback function (if not NULL) is called in the following
situations.
when we have generated a suspected prime number to test,
callback(0,num1++,cb_arg). When it passes a prime number test,
callback(1,num2++,cb_arg). When it is rejected as one of
the 2 primes required due to gcd(prime,e value) != 0,
callback(2,num3++,cb_arg). When finally accepted as one
of the 2 primes, callback(3,num4++,cb_arg).
==== rsaref.doc ========================================================
This package can be compiled to use the RSAref library.
This library is not allowed outside of the USA but inside the USA it is
claimed by RSA to be the only RSA public key library that can be used
besides BSAFE..
There are 2 files, rsaref/rsaref.c and rsaref/rsaref.h that contain the glue
code to use RSAref. These files were written by looking at the PGP
source code and seeing which routines it used to access RSAref.
I have also been sent by some-one a copy of the RSAref header file that
contains the library error codes.
[ Jun 1996 update - I have recently gotten hold of RSAref 2.0 from
South Africa and have been doing some performace tests. ]
They have now been tested against the recently announced RSAEURO
library.
There are 2 ways to use SSLeay and RSAref. First, to build so that
the programs must be linked with RSAref, add '-DRSAref' to CFLAG in the top
level makefile and -lrsaref (or where ever you are keeping RSAref) to
EX_LIBS.
To build a makefile via util/mk1mf.pl to do this, use the 'rsaref' option.
The second method is to build as per normal and link applications with
the RSAglue library. The correct library order would be
cc -o cmd cmd.o -lssl -lRSAglue -lcrypto -lrsaref -ldes
The RSAglue library is built in the rsa directory and is NOT
automatically installed.
Be warned that the RSAEURO library, that is claimed to be compatible
with RSAref contains a different value for the maximum number of bits
supported. This changes structure sizes and so if you are using
RSAEURO, change the value of RSAref_MAX_BITS in rsa/rsaref.h
==== s_mult.doc ========================================================
s_mult is a test program I hacked up on a Sunday for testing non-blocking
IO. It has a select loop at it's centre that handles multiple readers
and writers.
Try the following command
ssleay s_mult -echo -nbio -ssl -v
echo - sends any sent text back to the sender
nbio - turns on non-blocking IO
ssl - accept SSL connections, default is normal text
v - print lots
type Q<cr> to quit
In another window, run the following
ssleay s_client -pause </etc/termcap
The pause option puts in a 1 second pause in each read(2)/write(2) call
so the other end will have read()s fail.
==== session.doc ========================================================
I have just checked over and re-worked the session stuff.
The following brief example will ignore all setup information to do with
authentication.
Things operate as follows.
The SSL environment has a 'context', a SSL_CTX structure. This holds the
cached SSL_SESSIONS (which can be reused) and the certificate lookup
information. Each SSL structure needs to be associated with a SSL_CTX.
Normally only one SSL_CTX structure is needed per program.
SSL_CTX *SSL_CTX_new(void );
void SSL_CTX_free(SSL_CTX *);
These 2 functions create and destroy SSL_CTX structures
The SSL_CTX has a session_cache_mode which is by default,
in SSL_SESS_CACHE_SERVER mode. What this means is that the library
will automatically add new session-id's to the cache upon successful
SSL_accept() calls.
If SSL_SESS_CACHE_CLIENT is set, then client certificates are also added
to the cache.
SSL_set_session_cache_mode(ctx,mode) will set the 'mode' and
SSL_get_session_cache_mode(ctx) will get the cache 'mode'.
The modes can be
SSL_SESS_CACHE_OFF - no caching
SSL_SESS_CACHE_CLIENT - only SSL_connect()
SSL_SESS_CACHE_SERVER - only SSL_accept()
SSL_SESS_NO_CACHE_BOTH - Either SSL_accept() or SSL_connect().
If SSL_SESS_CACHE_NO_AUTO_CLEAR is set, old timed out sessions are
not automatically removed each 255, SSL_connect()s or SSL_accept()s.
By default, upon every 255 successful SSL_connect() or SSL_accept()s,
the cache is flush. Please note that this could be expensive on
a heavily loaded SSL server, in which case, turn this off and
clear the cache of old entries 'manually' (with one of the functions
listed below) every few hours. Perhaps I should up this number, it is hard
to say. Remember, the '255' new calls is just a mechanism to get called
every now and then, in theory at most 255 new session-id's will have been
added but if 100 are added every minute, you would still have
500 in the cache before any would start being flushed (assuming a 3 minute
timeout)..
int SSL_CTX_sess_hits(SSL_CTX *ctx);
int SSL_CTX_sess_misses(SSL_CTX *ctx);
int SSL_CTX_sess_timeouts(SSL_CTX *ctx);
These 3 functions return statistics about the SSL_CTX. These 3 are the
number of session id reuses. hits is the number of reuses, misses are the
number of lookups that failed, and timeouts is the number of cached
entries ignored because they had timeouted.
ctx->new_session_cb is a function pointer to a function of type
int new_session_callback(SSL *ssl,SSL_SESSION *new);
This function, if set in the SSL_CTX structure is called whenever a new
SSL_SESSION is added to the cache. If the callback returns non-zero, it
means that the application will have to do a SSL_SESSION_free()
on the structure (this is
to do with the cache keeping the reference counts correct, without the
application needing to know about it.
The 'active' parameter is the current SSL session for which this connection
was created.
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,int (*cb)());
to set the callback,
int (*cb)() SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)
to get the callback.
If the 'get session' callback is set, when a session id is looked up and
it is not in the session-id cache, this callback is called. The callback is
of the form
SSL_SESSION *get_session_callback(unsigned char *sess_id,int sess_id_len,
int *copy);
The get_session_callback is intended to return null if no session id is found.
The reference count on the SSL_SESSION in incremented by the SSL library,
if copy is 1. Otherwise, the reference count is not modified.
void SSL_CTX_sess_set_get_cb(ctx,cb) sets the callback and
int (*cb)()SSL_CTX_sess_get_get_cb(ctx) returns the callback.
These callbacks are basically intended to be used by processes to
send their session-id's to other processes. I currently have not implemented
non-blocking semantics for these callbacks, it is upto the application
to make the callbacks efficient if they require blocking (perhaps
by 'saving' them and then 'posting them' when control returns from
the SSL_accept().
LHASH *SSL_CTX_sessions(SSL_CTX *ctx)
This returns the session cache. The lhash strucutre can be accessed for
statistics about the cache.
void lh_stats(LHASH *lh, FILE *out);
void lh_node_stats(LHASH *lh, FILE *out);
void lh_node_usage_stats(LHASH *lh, FILE *out);
can be used to print details about it's activity and current state.
You can also delve directly into the lhash structure for 14 different
counters that are kept against the structure. When I wrote the lhash library,
I was interested in gathering statistics :-).
Have a read of doc/lhash.doc in the SSLeay distribution area for more details
on the lhash library.
Now as mentioned ealier, when a SSL is created, it needs a SSL_CTX.
SSL * SSL_new(SSL_CTX *);
This stores a session. A session is secret information shared between 2
SSL contexts. It will only be created if both ends of the connection have
authenticated their peer to their satisfaction. It basically contains
the information required to use a particular secret key cipher.
To retrieve the SSL_CTX being used by a SSL,
SSL_CTX *SSL_get_SSL_CTX(SSL *s);
Now when a SSL session is established between to programs, the 'session'
information that is cached in the SSL_CTX can me manipulated by the
following functions.
int SSL_set_session(SSL *s, SSL_SESSION *session);
This will set the SSL_SESSION to use for the next SSL_connect(). If you use
this function on an already 'open' established SSL connection, 'bad things
will happen'. This function is meaning-less when used on a ssl strucutre
that is just about to be used in a SSL_accept() call since the
SSL_accept() will either create a new session or retrieve one from the
cache.
SSL_SESSION *SSL_get_session(SSL *s);
This will return the SSL_SESSION for the current SSL, NULL if there is
no session associated with the SSL structure.
The SSL sessions are kept in the SSL_CTX in a hash table, to remove a
session
void SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
and to add one
int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
SSL_CTX_add_session() returns 1 if the session was already in the cache (so it
was not added).
Whenever a new session is created via SSL_connect()/SSL_accept(),
they are automatically added to the cache, depending on the session_cache_mode
settings. SSL_set_session()
does not add it to the cache. Just call SSL_CTX_add_session() if you do want the
session added. For a 'client' this would not normally be the case.
SSL_CTX_add_session() is not normally ever used, except for doing 'evil' things
which the next 2 funtions help you do.
int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,unsigned char **pp,long length);
These 2 functions are in the standard ASN1 library form and can be used to
load and save to a byte format, the SSL_SESSION structure.
With these functions, you can save and read these structures to a files or
arbitary byte string.
The PEM_write_SSL_SESSION(fp,x) and PEM_read_SSL_SESSION(fp,x,cb) will
write to a file pointer in base64 encoding.
What you can do with this, is pass session information between separate
processes. Please note, that you will probably also need to modify the
timeout information on the SSL_SESSIONs.
long SSL_get_time(SSL_SESSION *s)
will return the 'time' that the session
was loaded. The timeout is relative to this time. This information is
saved when the SSL_SESSION is converted to binarary but it is stored
in as a unix long, which is rather OS dependant, but easy to convert back.
long SSL_set_time(SSL_SESSION *s,long t) will set the above mentioned time.
The time value is just the value returned from time(3), and should really
be defined by be to be time_t.
long SSL_get_timeout(SSL_SESSION *s);
long SSL_set_timeout(SSL_SESSION *s,long t);
These 2 retrieve and set the timeout which is just a number of secconds
from the 'SSL_get_time()' value. When this time period has elapesed,
the session will no longer be in the cache (well it will actually be removed
the next time it is attempted to be retrieved, so you could 'bump'
the timeout so it remains valid).
The 'time' and 'timeout' are set on a session when it is created, not reset
each time it is reused. If you did wish to 'bump it', just after establishing
a connection, do a
SSL_set_time(ssl,time(NULL));
You can also use
SSL_CTX_set_timeout(SSL_CTX *ctx,unsigned long t) and
SSL_CTX_get_timeout(SSL_CTX *ctx) to manipulate the default timeouts for
all SSL connections created against a SSL_CTX. If you set a timeout in
an SSL_CTX, all new SSL's created will inherit the timeout. It can be over
written by the SSL_set_timeout(SSL *s,unsigned long t) function call.
If you 'set' the timeout back to 0, the system default will be used.
SSL_SESSION *SSL_SESSION_new();
void SSL_SESSION_free(SSL_SESSION *ses);
These 2 functions are used to create and dispose of SSL_SESSION functions.
You should not ever normally need to use them unless you are using
i2d_SSL_SESSION() and/or d2i_SSL_SESSION(). If you 'load' a SSL_SESSION
via d2i_SSL_SESSION(), you will need to SSL_SESSION_free() it.
Both SSL_set_session() and SSL_CTX_add_session() will 'take copies' of the
structure (via reference counts) when it is passed to them.
SSL_CTX_flush_sessions(ctx,time);
The first function will clear all sessions from the cache, which have expired
relative to 'time' (which could just be time(NULL)).
SSL_CTX_flush_sessions(ctx,0);
This is a special case that clears everything.
As a final comment, a 'session' is not enough to establish a new
connection. If a session has timed out, a certificate and private key
need to have been associated with the SSL structure.
SSL_copy_session_id(SSL *to,SSL *from); will copy not only the session
strucutre but also the private key and certificate associated with
'from'.
EXAMPLES.
So lets play at being a weird SSL server.
/* setup a context */
ctx=SSL_CTX_new();
/* Lets load some session from binary into the cache, why one would do
* this is not toally clear, but passing between programs does make sense
* Perhaps you are using 4096 bit keys and are happy to keep them
* valid for a week, to avoid the RSA overhead of 15 seconds, I'm not toally
* sure, perhaps this is a process called from an SSL inetd and this is being
* passed to the application. */
session=d2i_SSL_SESSION(....)
SSL_CTX_add_session(ctx,session);
/* Lets even add a session from a file */
session=PEM_read_SSL_SESSION(....)
SSL_CTX_add_session(ctx,session);
/* create a new SSL structure */
ssl=SSL_new(ctx);
/* At this point we want to be able to 'create' new session if
* required, so we need a certificate and RSAkey. */
SSL_use_RSAPrivateKey_file(ssl,...)
SSL_use_certificate_file(ssl,...)
/* Now since we are a server, it make little sence to load a session against
* the ssl strucutre since a SSL_accept() will either create a new session or
* grab an existing one from the cache. */
/* grab a socket descriptor */
fd=accept(...);
/* associated it with the ssl strucutre */
SSL_set_fd(ssl,fd);
SSL_accept(ssl); /* 'do' SSL using out cert and RSA key */
/* Lets print out the session details or lets save it to a file,
* perhaps with a secret key cipher, so that we can pass it to the FBI
* when they want to decode the session :-). While we have RSA
* this does not matter much but when I do SSLv3, this will allow a mechanism
* for the server/client to record the information needed to decode
* the traffic that went over the wire, even when using Diffie-Hellman */
PEM_write_SSL_SESSION(SSL_get_session(ssl),stdout,....)
Lets 'connect' back to the caller using the same session id.
ssl2=SSL_new(ctx);
fd2=connect(them);
SSL_set_fd(ssl2,fd2);
SSL_set_session(ssl2,SSL_get_session(ssl));
SSL_connect(ssl2);
/* what the hell, lets accept no more connections using this session */
SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl),SSL_get_session(ssl));
/* we could have just as easily used ssl2 since they both are using the
* same session.
* You will note that both ssl and ssl2 are still using the session, and
* the SSL_SESSION structure will be free()ed when both ssl and ssl2
* finish using the session. Also note that you could continue to initiate
* connections using this session by doing SSL_get_session(ssl) to get the
* existing session, but SSL_accept() will not be able to find it to
* use for incoming connections.
* Of corse, the session will timeout at the far end and it will no
* longer be accepted after a while. The time and timeout are ignored except
* by SSL_accept(). */
/* Since we have had our server running for 10 weeks, and memory is getting
* short, perhaps we should clear the session cache to remove those
* 100000 session entries that have expired. Some may consider this
* a memory leak :-) */
SSL_CTX_flush_sessions(ctx,time(NULL));
/* Ok, after a bit more time we wish to flush all sessions from the cache
* so that all new connections will be authenticated and incure the
* public key operation overhead */
SSL_CTX_flush_sessions(ctx,0);
/* As a final note, to copy everything to do with a SSL, use */
SSL_copy_session_id(SSL *to,SSL *from);
/* as this also copies the certificate and RSA key so new session can
* be established using the same details */
==== sha.doc ========================================================
The SHA (Secure Hash Algorithm) library.
SHA is a message digest algorithm that can be used to condense an arbitrary
length message down to a 20 byte hash. The functions all need to be passed
a SHA_CTX which is used to hold the SHA context during multiple SHA_Update()
function calls. The normal method of use for this library is as follows
This library contains both SHA and SHA-1 digest algorithms. SHA-1 is
an update to SHA (which should really be called SHA-0 now) which
tweaks the algorithm slightly. The SHA-1 algorithm is used by simply
using SHA1_Init(), SHA1_Update(), SHA1_Final() and SHA1() instead of the
SHA*() calls
SHA_Init(...);
SHA_Update(...);
...
SHA_Update(...);
SHA_Final(...);
This library requires the inclusion of 'sha.h'.
The functions are as follows:
void SHA_Init(
SHA_CTX *c);
This function needs to be called to initiate a SHA_CTX structure for
use.
void SHA_Update(
SHA_CTX *c;
unsigned char *data;
unsigned long len);
This updates the message digest context being generated with 'len'
bytes from the 'data' pointer. The number of bytes can be any
length.
void SHA_Final(
unsigned char *md;
SHA_CTX *c;
This function is called when a message digest of the data digested
with SHA_Update() is wanted. The message digest is put in the 'md'
array and is SHA_DIGEST_LENGTH (20) bytes long.
unsigned char *SHA(
unsigned char *d;
unsigned long n;
unsigned char *md;
This function performs a SHA_Init(), followed by a SHA_Update()
followed by a SHA_Final() (using a local SHA_CTX).
The resulting digest is put into 'md' if it is not NULL.
Regardless of the value of 'md', the message
digest is returned from the function. If 'md' was NULL, the message
digest returned is being stored in a static structure.
==== speed.doc ========================================================
To get an idea of the performance of this library, use
ssleay speed
perl util/sp-diff.pl file1 file2
will print out the relative differences between the 2 files which are
expected to be the output from the speed program.
The performace of the library is very dependant on the Compiler
quality and various flags used to build.
---
These are some numbers I did comparing RSAref and SSLeay on a Pentium 100.
[ These numbers are all out of date, as of SSL - 0.6.1 the RSA
operations are about 2 times faster, so check the version number ]
RSA performance.
SSLeay 0.6.0
Pentium 100, 32meg, Windows NT Workstation 3.51
linux - gcc v 2.7.0 -O3 -fomit-frame-pointer -m486
and
Windows NT - Windows NT 3.51 - Visual C++ 4.1 - 586 code + 32bit assember
Windows 3.1 - Windows NT 3.51 - Visual C++ 1.52c - 286 code + 32bit assember
NT Dos Shell- Windows NT 3.51 - Visual C++ 1.52c - 286 code + 16bit assember
Times are how long it takes to do an RSA private key operation.
512bits 1024bits
-------------------------------
SSLeay NT dll 0.042s 0.202s see above
SSLeay linux 0.046s 0.218s Assember inner loops (normal build)
SSLeay linux 0.067s 0.380s Pure C code with BN_LLONG defined
SSLeay W3.1 dll 0.108s 0.478s see above
SSLeay linux 0.109s 0.713s C without BN_LLONG.
RSAref2.0 linux 0.149s 0.936s
SSLeay MS-DOS 0.197s 1.049s see above
486DX66, 32meg, Windows NT Server 3.51
512bits 1024bits
-------------------------------
SSLeay NT dll 0.084s 0.495s <- SSLeay 0.6.3
SSLeay NT dll 0.154s 0.882s
SSLeay W3.1 dll 0.335s 1.538s
SSLeay MS-DOS 0.490s 2.790s
What I find cute is that I'm still faster than RSAref when using standard C,
without using the 'long long' data type :-), %35 faster for 512bit and we
scale up to 3.2 times faster for the 'default linux' build. I should mention
that people should 'try' to use either x86-lnx.s (elf), x86-lnxa.s or
x86-sol.s for any x86 based unix they are building on. The only problems
with be with syntax but the performance gain is quite large, especially for
servers. The code is very simple, you just need to modify the 'header'.
The message is, if you are stuck using RSAref, the RSA performance will be
bad. Considering the code was compiled for a pentium, the 486DX66 number
would indicate 'Use RSAref and turn you Pentium 100 into a 486DX66' :-).
[ As of verson 0.6.1, it would be correct to say 'turn you pentium 100
into a 486DX33' :-) ]
I won't tell people if the DLL's are using RSAref or my stuff if no-one
asks :-).
eric
PS while I know I could speed things up further, I will probably not do
so due to the effort involved. I did do some timings on the
SSLeay bignum format -> RSAref number format conversion that occurs
each time RSAref is used by SSLeay, and the numbers are trivial.
0.00012s a call for 512bit vs 0.149s for the time spent in the function.
0.00018s for 1024bit vs 0.938s. Insignificant.
So the 'way to go', to support faster RSA libraries, if people are keen,
is to write 'glue' code in a similar way that I do for RSAref and send it
to me :-).
My base library still has the advantage of being able to operate on
any size numbers, and is not that far from the performance from the
leaders in the field. (-%30?)
[ Well as of 0.6.1 I am now the leader in the filed on x86 (we at
least very close :-) ]
I suppose I should also mention some other numbers RSAref numbers, again
on my Pentium.
DES CBC EDE-DES MD5
RSAref linux 830k/s 302k/s 4390k/s
SSLeay linux 855k/s 319k/s 10025k/s
SSLeay NT 1158k/s 410k/s 10470k/s
SSLeay w31 378k/s 143k/s 2383k/s (fully 16bit)
Got to admit that Visual C++ 4.[01] is a damn fine compiler :-)
--
Eric Young | BOOL is tri-state according to Bill Gates.
AARNet: eay@cryptsoft.com | RTFM Win32 GetMessage().