diff --git a/demo/mdemo.c b/demo/mdemo.c old mode 100755 new mode 100644 diff --git a/demo/randemo.c b/demo/randemo.c old mode 100755 new mode 100644 diff --git a/demo/redemo.c b/demo/redemo.c old mode 100755 new mode 100644 diff --git a/docs/asm.inf b/docs/asm.inf old mode 100755 new mode 100644 diff --git a/docs/bugs.txt b/docs/bugs.txt old mode 100755 new mode 100644 index 077799d..78bc979 --- a/docs/bugs.txt +++ b/docs/bugs.txt @@ -2,13 +2,13 @@ Version 1.0 -This is the RSAEURO Beta testers bug report form, please complete -this if during your use you encounter a problem. Once complete -please either e-mail or post a copy to me. This can also be used -for comments and suggestions. +This is the RSAEURO report form, please complete this if during +your use you encounter a problem. Once complete please either +e-mail or post a copy to me. This can also be used for comments +and suggestions. -You may also contact me by telephone but only after 7pm weekdays -or anytime weekends, on +44 (1200) 448241 and ask for Stephen. +You may also contact me by telephone on +44 (468) 286034 weekdays +or weekends, on +44 (1200) 448241 and ask for Stephen. Bug Report: @@ -64,5 +64,5 @@ Details:- Please write "RSAEURO BUGS" in top left of envelope. - 3. Phone: +44 (1200) 448241 - After 7pm Weekdays, Anytime Weekends. \ No newline at end of file + 3. Phone: +44 (468) 286034 Daytime during weekdays. + +44 (1200) 448241 After 7pm Weekdays, Anytime Weekends. diff --git a/docs/history b/docs/history old mode 100755 new mode 100644 index d2cd84f..c57ac22 --- a/docs/history +++ b/docs/history @@ -1,36 +1,36 @@ -Revision History of RSAEURO - -0.90 - July 1994. - First Alpha Versions, most functions implemented. - -0.91 - Sept. 1994. - Bulk of Code complete, Math functions partly complete. - -0.92 - Oct. 1994. - Some assembler support added for Intel x86 processors. - Math routines problems on PC and Sun SPARC. - -0.93 - Feb. 1995. - Math routines complete, 680x0 assembler support added. - In house testing started. - -0.93 - April 1995. - Goes to Beta.. - -1.00 - June 1995. - Fixed Documentation and produced distribution for release. - RSAEURO Released. - -1.01 - August 1995. - Documentation updated with new rsaeuro e-mail addresses. - Random Objects code for R_RandomCreate and R_RandomMix - modified. - -1.02 - October 1995. - Fixed a number of minor bugs and fixed problem with Math - library caused it not to work that well with 16-bit - compilers. - ----- -J.S.Kapp - Sun 08/10/95 15:51:35 - +Revision History of RSAEURO + +0.90 - July 1994. + First Alpha Versions, most functions implemented. + +0.91 - Sept. 1994. + Bulk of Code complete, Math functions partly complete. + +0.92 - Oct. 1994. + Some assembler support added for Intel x86 processors. + Math routines problems on PC and Sun SPARC. + +0.93 - Feb. 1995. + Math routines complete, 680x0 assembler support added. + In house testing started. + +0.93 - April 1995. + Goes to Beta.. + +1.00 - June 1995. + Fixed Documentation and produced distribution for release. + RSAEURO Released. + +1.01 - August 1995. + Documentation updated with new rsaeuro e-mail addresses. + Random Objects code for R_RandomCreate and R_RandomMix + modified. + +1.02 - October 1995. + Fixed a number of minor bugs and fixed problem with Math + library caused it not to work that well with 16-bit + compilers. + +---- +J.S.Kapp - Sun 08/10/95 15:51:35 + diff --git a/docs/licence.txt b/docs/licence.txt old mode 100755 new mode 100644 index b0f0dd7..c20cfdd --- a/docs/licence.txt +++ b/docs/licence.txt @@ -1,8 +1,8 @@ - RSAEURO - TOOLKIT LICENSE AGREEMENT - June 23rd, 1995. + RSAEURO + TOOLKIT LICENSE AGREEMENT + 17th April 1996. - Copyright (c) J.S.A.Kapp, 1994-1995. + Copyright (c) J.S.A.Kapp, 1994-1996. 1. LICENSE. J.S.A.Kapp grants you a nonexclusive, non-transferable, perpetual (subject to the conditions of section 7) license for the @@ -82,8 +82,8 @@ on distribution media, is co-located or stored with the Toolkit. developed with RSAEURO may be subject to export controls in some countries. If you are located in the United States and develop such applications using RSAEURO, you are advised to obtain a copy of RSAREF - from RSADSI, as you may using RSAEURO infringe on Patents held by - Public Key Partners of Sunnydale California. + from RSADSI, as you may using RSAEURO infringe on Patents held by RSA + Data Security and Cylink. 7. The license granted hereunder is effective until terminated. You may terminate it at anytime by destroying all components of the Toolkit and @@ -106,6 +106,7 @@ on distribution media, is co-located or stored with the Toolkit. BB7 3BB. Tel. (+44) 1200-448241 + Tel. (+44) 468-286034 ii. For details of Export Controls and other controls regarding the use of cryptographic techniques please contact your country's diff --git a/docs/redemo.ps b/docs/redemo.ps old mode 100755 new mode 100644 index c3ba7f8..b153b49 Binary files a/docs/redemo.ps and b/docs/redemo.ps differ diff --git a/docs/redemo.txt b/docs/redemo.txt old mode 100755 new mode 100644 diff --git a/docs/rsaedoc.doc b/docs/rsaedoc.doc new file mode 100644 index 0000000..aba5349 Binary files /dev/null and b/docs/rsaedoc.doc differ diff --git a/docs/rsaedoc.htm b/docs/rsaedoc.htm new file mode 100644 index 0000000..4038478 --- /dev/null +++ b/docs/rsaedoc.htm @@ -0,0 +1,3191 @@ + +RSAEURO Version 1.03 Documentation + +
+

RSAEURO

+
Version 1.03
+
+
    +
  1. INTRODUCTION
  2. +
  3. RANDOM NUMBERS
  4. +
  5. MESSAGE DIGESTS
  6. +
  7. DIGITAL SIGNATURE ROUTINES
  8. +
  9. ENVELOPE PROCESSING
  10. +
  11. PEM FUNCTIONS
  12. +
  13. KEY GENERATION AND EXCHANGE
  14. +
  15. RSA
  16. +
  17. DES
  18. +
  19. NATURAL NUMBER ARITHMETIC
  20. +
  21. MEMORY MANIPULATION
  22. +
  23. TECHNICAL INFORMATION
  24. +
  25. APPENDIX A: FUNCTION CROSS-REFERENCE
+

+ + +

+
+

+INTRODUCTION

+
    +
  1. What is RSAEURO? +
  2. +
  3. What is covered by this document? +
  4. +
  5. Contact information +
  6. +
  7. Typographic conventions +
  8. +
  9. Licence +
  10. +
  11. Patents and trademarks
      +
    1. RSADSI +
    2. +
    3. Cylink
    4. +
  12. +
  13. Release history
      +
    1. Release 1.00 +
    2. +
    3. Release 1.01 +
    4. +
    5. Release 1.02 +
    6. +
    7. Release 1.03
  14. +
+

+What is RSAEURO? +

+

RSAEURO is a cryptographic toolkit providing various functions for the use +of digital signatures, data encryption and supporting areas (PEM encoding, +random number generation etc). To aid compatibility with existing +software, RSAEURO is call-compatible with RSADSI's "RSAREF" toolkit. +RSAEURO allows non-US residents to make use of much of the cryptographic +software previously only (legally) available in the US. +

+
+

IMPORTANT NOTICE: Please do not distribute or use this +software in the US-it is illegal to use this toolkit in the US, as +public-key cryptography is covered by US patents (see the Patents and Trademarks +section below for details). If you are a US resident, please use the RSAREF +toolkit instead. +

+
+

RSAEURO contains support for the following: +

+ +

+What is covered by this document? +

+

This document provides a function-by-function description of the RSAEURO +toolkit, at a sufficient level of detail to allow the use of the toolkit within +other software. The internal workings of the functions are not described. For +full details of the internal workings of the RSAEURO routines, please consult +the (well commented) source code.

+

+It is assumed that the reader is familiar with C programming and basic +cryptography, although a detailed knowledge is not required.

+

+This document is divided into the following sections: +

+
Introduction (This section).
+
General introduction to RSAEURO.
+
Random numbers
+
Routines for generating cryptographically-secure random numbers, for use by +various other cryptographic functions.
+
Message digests
+
Routines for the creation and verification of message digests.
+
Digital signatures
+
Routines for the creation and verification of digital signatures.
+
Envelope processing
+
Routines for the creation and use of digital "envelopes" (an "envelope" +is a structure containing encrypted data and an optional digital signature).
+
PEM functions
+
Routines for processing Interned privacy-enhanced mail (PEM) encoded +messages.
+
Key generation and exchange
+
Routines for generating key material for RSA encryption, and exchanging +keys via Diffie-Hellman agreement.
+
RSA
+
Routines for public key encryption and decryption using RSA and PKCS#1.
+
DES
+
Routines for secret-key encryption and decryption using DES in CBC mode, +with either single or triple-key operation.
+
Natural number arithmetic
+
Low-level routines for performing natural number arithmetic.
+
Memory manipulation
+
Platform-specific memory manipulation routines.
+
Technical information
+
"Technical" programming information, including descriptions of +RSAEURO data structures, defined values and references to further information.
+
Appendix A: Function cross-reference +
+
An alphabetical list of functions with brief details and a reference to +coverage in the main documentation.
+

+Contact information +

+

All general comments should be sent to +rsaeuro@sourcery.demon.co.uk. + Bug reports should be sent to +rsaeuro-bugs@sourcery.demon.co.uk. + Comments or corrections regarding the documentation should be sent to +nikb@cix.compulink.co.uk.

+

+As a last resort, the author may be contacted by "snail-mail" at the +following address:

+

+Stephen Kapp
The Post Office
Nr. Clitheroe
Lancashire
BB7 3BB
UNITED +KINDOM + +

+

+Typographic conventions +

+

Throughout this document, blocks of C source code are set in +courier , and in-text references to functions, constants and the +like are set in bold. Conventional C-style mathematical operators are +used throughout (e.g. * for "times", / for "divided by" +etc) + +

+

+Licence

+

RSAEURO TOOLKIT LICENSE AGREEMENT 15th December 1995

+

+ Copyright (c) J.S.A.Kapp, 1994-1995. 1. LICENSE. J.S.A.Kapp grants you a +nonexclusive, non-transferable, perpetual (subject to the conditions of section +7) license for the "RSAEURO" toolkit (the "Toolkit") and its +associated documentation, subject to all of the following terms and conditions:

+

+i. To use the Toolkit on any computer in your possession.

+

+ii. to make copies of the Toolkit for back-up purposes.

+

+iii. to modify the Toolkit in any manner for porting or performance improvement +purposes (subject to Section 2) or to incorporate the Toolkit into other +computer programs for your own personal or internal use, provided that you +provide J.S.A.Kapp with a copy of any such modification or Application Program +by electronic mail, and grant J.S.A.Kapp a perpetual, royalty-free license to +use and distribute such modifications and Application Programs on the terms set +forth in this Agreement.

+

+iv. To copy and distribute the Toolkit and Application Programs in accordance +with the limitations set forth in Section 2.

+

+ "Application Programs" are programs that incorporate all or any +portion of the Toolkit in any form. The restrictions imposed on Application +Programs in this Agreement shall not apply to any software which through the +mere aggregation on distribution media, is co-located or stored with the +Toolkit.

+

+2. LIMITATIONS ON LICENSE.

+

+i. J.S.A.Kapp owns the Toolkit and its associated documentation and all +copyrights therein. You may only use, copy, modify and distribute the Toolkit as +expressly provided for in this Agreement. You must reproduce and include this +Agreement, J.S.A.Kapp's copyright notices and disclaimer of warranty on any copy +and its associated documentation.

+

+ii. The Toolkit and its associated documentation are freeware for noncommercial +purposes, however for commercial purposes please contact J.S.A.Kapp for +licensing details.

+

+iii. The Toolkit and Application Programs are to be used for noncommercial +purposes. However, media costs associated with the distribution of the Program +or Application Programs may be recovered.

+

+iv. The Toolkit, if modified, must carry prominent notices stating that changes +have been made, and the dates of any such changes. v. Prior permission from +J.S.A.Kapp is required for any modifications that access the Toolkit through +ways other than the published Toolkit interface or for modifications to the +Toolkit interface, and structures. J.S.A.Kapp will grant all reasonable requests +for permission to make such modifications.

+

+3. You are solely responsible for all of your costs and expenses incurred in +connection with the distribution of the Toolkit or any Application Program +hereunder, and J.S.A.Kapp shall have no liability, obligation or responsibility +there of. J.S.A.Kapp shall have no obligation to provide maintenance, support, +upgrades or new releases to you or to any distributee of the Toolkit or any +Application Program.

+

+4. THE TOOLKIT AND ITS ASSOCIATED DOCUMENTATION ARE LICENSED "AS IS" +WITHOUT WARRANTY AS TO THEIR PERFORMANCE, MERCHANTABILITY OR FITNESS FOR ANY +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE RESULTS AND PERFORMANCE OF THE +TOOLKIT IS ASSUMED BY YOU AND YOUR DISTRIBUTEES. SHOULD THE TOOLKIT PROVE +DEFECTIVE, YOU AND YOUR DISTRIBUTEES (AND NOT J.S.A.KAPP) ASSUME THE ENTIRE COST +OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+

+5. LIMITATION OF LIABILITY, NEITHER J.S.A.KAPP NOR ANY OTHER PERSON WHO HAS BEEN +INVOLVED IN THE CREATION, PRODUCTION, OR DELIVERY OF THE TOOLKIT SHALL BE LIABLE +TO YOU OR TO ANY OTHER PERSON FOR ANY DIRECT, INCIDENTAL OR CONSEQUENTIAL +DAMAGES, EVEN IF J.S.A.KAPP HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

+

+6. RSAEURO is a publication of cryptographic techniques. Applications developed +with RSAEURO may be subject to export controls in some countries. If you are +located in the United States and develop such applications using RSAEURO, you +are advised to obtain a copy of RSAREF from RSADSI, as you may using RSAEURO +infringe on Patents held by RSA Data Security and Cylink.

+

+7. The license granted hereunder is effective until terminated. You may +terminate it at anytime by destroying all components of the Toolkit and its +associated documentation. The termination of your license will not result in the +termination of the licenses of any distributees who have received rights to the +Toolkit through you so long as they are in compliance with the provisions of +this license.

+

+8. GENERAL

+

+i. Address all correspondence regarding this license to J.S.A.Kapp's electronic +mail address <rsaeuro@sourcery.demon.co.uk>, +or to

+

+ Mr J.S.A.Kapp.
The Post Office,
Dunsop Bridge,
Clitheroe, +
Lancashire,
England.
BB7 3BB.

Tel. (+44) 1200-448241

+

+ii. For details of Export Controls and other controls regarding the use of +cryptographic techniques please contact your country's relevant authority. + +

+

+Patents and trademarks +

+

The following terms are registered trademarks as indicated. All other +trademarks acknowledged. To the author's knowledge, all relevant trademarks have +been duly acknowledged. If there are any omissions, please provide the relevant +details and the documentation will be amended accordingly. + +

+

+RSADSI

+

RSA Data Security Inc (RSADSI) provide consultancy and software engineering +service in the field of cryptography. The RSAREF toolkit, on which RSAEURO is +modelled, is available free of charge from RSADSI with the USA and Canada, +subject to their licensing agreement. For information regarding licensing +RSADSI's toolkits, contact Paul Gordon (paul@rsa.com) +at RSADSI.

+

+Following a recent arbitration between RSADSI and Cylink, it has been determined +that RSADSI hold patent rights to the RSA public-key cryptographic algorithm. +For details of licensing the RSA algorithm contact Paul Livesay (pol@rsa.com)at RSADSI.

+

+RSADSI can be contacted at:

RSA Data Security Inc,
10 Twin Dolphin +Drive
Redwood City
CA 94065

Tel. (415) 595-8782.

+

+DESX and RSAREF are registered trademarks of RSADSI. + +

+

+Cylink

+

At the time of writing it was not possible to determine the legal situation +regarding patents regarding cryptography held by Cylink. Interested parties +should contact Bob Fougner on (+1) 408 735 5893, e-mail: +fougner@cylink.com. + +

+

+Release history +

+

This section describes the changes made at each release of the software.

+

+ +

+

+Release 1.00 +

+

First major release. + +

+

+Release 1.01 +

+

Modifications: +

+ +

+Release 1.02 +

+

Bug fixes: +

+ +

+Release 1.03 +

+

Bug fixes: +

+ +

+

+
+

+RANDOM NUMBERS +

+
    +
  1. Introduction +
  2. +
  3. Functions
      +
    1. R_RandomInit +
    2. +
    3. R_RandomUpdate +
    4. +
    5. R_GetRandomBytesNeeded +
    6. +
    7. R_GenerateBytes +
    8. +
    9. R_RandomFinal +
    10. +
    11. R_RandomCreate +
    12. +
    13. R_RandomMix
  4. +
+

RSAEURO Full documentation, revision 0.90. 18/08/95. + +

+

+Introduction

+

Various functions within RSAEURO require random data (primarily for key +generation). A stream of random (strictly, pseudo-random) data is generated +using the MD5 digest algorithm and a "seed" value, which is provided +in the form of the random structure.

+

+Before use, the random structure must be initialised and "seeded" +itself, by "mixing in" an amount of genuine random data. The +procedure for preparing a new random structure is as follows: +

+
    +
  1. Reserve sizeof(R_RANDOM_STRUCT) memory. +
  2. +
  3. Initialise the new structure using R_RandomInit. This sets +random- + >bytesNeeded, the number of random bytes required to "seed" +the structure before use, to RANDOM_BYTES_RQ, and zeroes the data. +
  4. +
  5. "Mix in" a suitable quantity of random data using R_RandomUpdate. +R_RandomUpdate takes a caller-supplied block of data and combines it +with the existing random structure using MD5. R_RandomUpdate also +decrements random->bytesNeeded, which indicates the amount of random +data still required (the R_GetRandomBytesNeeded function returns the +bytesNeeded value of a given random structure). +R_RandomUpdate should be called repeatedly until +R_GetRandomBytesNeeded returns zero.
+

R_RandomUpdate may be called once the structure has been initialised +(i.e. bytesNeeded equals zero). RANDOM_BYTES_RQ should be +adjusted according to the "purity" of the random data source.

+

+An additional function, R_RandomCreate, creates and initialises a "fresh" +random structure using data from the current system clock, via the ANSI +gmtime function (this function uses a separate variable, +RANDOM_BYTES_INT, to indicate the amount of mix-in bytes, currently set to 512). + On ANSI-compliant systems, R_RandomCreate can be used as a "one-stop +shop" for producing a ready-to-use random structure. Other sources +of random data, such as keyboard timings, disk latency and so on are highly +system-dependant, and have not yet been implemented.

+

+Once a random structure has been created, initialised and seeded, it may +be used by R_GenerateBytes to produce a stream of pseudo-random data. +R_GenerateBytes returns an error if an invalid (non-seeded) +random structure is referenced.

+

+The function R_RandomMix uses the ANSI clock and time +functions to randomise the current state of an existing, initialised random +structure. Then flush any pending output from the output state.

+

+The function R_RandomFinal clears a random structure. + +

+

+Functions

+

+R_RandomInit

+

int R_RandomInit(random)R_RANDOM_STRUCT *random; /* random structure +*/

+

+Initialises a new random structure. Zeroes the data area and sets +random->bytesNeeded to the system default (RANDOM_BYTES_RQ). Always +returns IDOK. + +

+

+R_RandomUpdate

+

int R_RandomUpdate(random, block, len)
R_RANDOM_STRUCT +*random; /* random structure */
unsigned char *block; /* block of data */
unsigned +int len; /* length of block */

+

+Updates a previously initialised random structure by mixing in a block +of caller-supplied data using MD5. Updates random->bytesNeeded as +appropriate. Always returns IDOK. + +

+

+R_GetRandomBytesNeeded

+

int R_GetRandomBytesNeeded(bytesNeeded, random)
unsigned int +*bytesNeeded /* number of mix-in bytes needed */
R_RANDOM_STRUCT *random /* +random structure */

+

+Returns the number of seed bytes still required for the random +structure. On exit, bytesNeeded contains the number of bytes +required by the structure random. Always returns IDOK. + +

+

+R_GenerateBytes

+

int R_GenerateBytes(block, len, random)
unsigned char *block; /* +block */
unsigned int len; /* length of block */
R_RANDOM_STRUCT +*random; /* random structure */

+

+Populates block with len pseudo-random bytes derived from +random using MD5. Returns RE_NEED_RANDOM if random has not been fully +initialised, IDOK otherwise. + +

+

+R_RandomFinal

+

void R_RandomFinal(random)
R_RANDOM_STRUCT *random; /* random +structure */

+

+Clears a random structure, setting all values and data to zero. + +

+

+R_RandomCreate

+

void R_RandomCreate(random)
R_RANDOM_STRUCT *random; /* random +structure */

+

+Initialises a random structure and seeds it with data derived using the +ANSI gmtime and clock function. The quantity of seeding data is +defined by RANDOM_BYTES_RQINT. + +

+

+R_RandomMix

+

void R_RandomMix(random)
R_RANDOM_STRUCT *random;

+

+Randomises the internal state of the supplied random structure, using +data from the ANSI clock and time functions, then flushes any +pending output. + +

+
+

+MESSAGE DIGESTS +

+
    +
  1. Introduction +
  2. +
  3. Functions
      +
    1. R_DigestInit +
    2. +
    3. R_DigestUpdate +
    4. +
    5. R_DigestFinal +
    6. +
    7. R_DigestBlock +
    8. +
    9. MD2Init +
    10. +
    11. MD2Update +
    12. +
    13. MD2Final +
    14. +
    15. MD4Init +
    16. +
    17. MD4Update +
    18. +
    19. MD4Final +
    20. +
    21. MD5Init +
    22. +
    23. MD5Update +
    24. +
    25. MD5Final +
    26. +
    27. SHSInit +
    28. +
    29. SHSUpdate +
    30. +
    31. SHSFinal
  4. +
+

+Introduction

+

RSAEURO supports four different message digest algorithms: MD2, MD4, MD5 and +Secure Hash Standard (SHS). The current MD2, MD4 and MD5 routines are based on +source code made available by RSADSI.

+

+Support for each digest method consists of three basic functions: init, +which initialises the relevant structures and contexts; update, which +adds data to the digest, and final which "tidies up" and +returns the final digest value. To simplify implementation, the digest and +signature routines are called via "parent" routines, with the +algorithm to be used passed as a parameter.

+

+High-level functions are provided for processing data which is memory-resident. +These functions handle all memory allocation, initialisation and processing +internally, providing a "one-stop shop" solution. However, as the +data to be processed must be resident in memory, the run-time resource +requirements of these functions are larger than the init-update-final method.

+

+The procedure for producing a message digest is as follows: +

+
    +
  1. Initialise the digest "context", containing the digest generator +state, input buffer etc, by calling R_DigestInit. The digest +type (MD2, MD4, MD5 or SHS) is specified as a parameter to R_DigestInit. +
  2. +
  3. Process the source data a block at a time, using R_DigestUpdate. +
  4. +
  5. Produce the final digest value using R_DigestFinal.
+

The +R_Digest functions act as "wrappers" for the +algorithm-specific message digest routines. An additional function, R_DigestBlock, +may be used for memory-resident data. + +

+

+Functions

+

+R_DigestInit

+

int R_DigestInit(context, digesttype)
R_DIGEST_CTX *context; /* +new context */
int digesttype; /* message-digest algorithm */

+

+Initialises a context ready for digest production. The R_DIGEST_CTX type is a +union structure supporting the different context types required for each message +digest algorithm. context is a pointer to a "blank" +R_DIGEST_CTX structure, digesttype indicates the digest algorithm to be +used. Currently supported digest types are DA_MD2, DA_MD4, DA_MD5 and DA_SHS. +Returns RE_DIGEST_ALGORITHM if an invalid (unsupported) digest algorithm is +selected, IDOK otherwise. + +

+

+R_DigestUpdate

+

int R_DigestUpdate(context, partIn, partInLen)
R_DIGEST_CTX +*context; /* context */
unsigned char *partIn; /* next data part */
unsigned +int partInLen; /* length of next data part */

+

+Updates context using the appropriate digest algorithm (as indicated by +the context) with the supplied data. partIn points to the data block, +partInLen indicates the length of the block in bytes. Returns +RE_DIGEST_ALGORITHM if an invalid (unsupported) digest algorithm is selected, +IDOK otherwise. + +

+

+R_DigestFinal

+

int R_DigestFinal(context, digest, digestLen)
R_DIGEST_CTX +*context; /* context */
unsigned char *digest; /* message digest */
unsigned +int *digestLen; /* length of message digest */

+

+Produces the final digest value from context. On exit, digest +contains the message digest and digestLen indicates length of the digest +in bytes. R_DigestFinal also zeroes the context to remove any sensitive +data from memory. Returns RE_DIGEST_ALGORITHM if an invalid (unsupported) +digest algorithm is selected, IDOK otherwise. + +

+

+R_DigestBlock

+

int R_DigestBlock(digest, digestLen, block, blockLen, +digestAlgorithm)
unsigned char *digest; /* message digest */
unsigned +int *digestLen; /* length of message digest */
unsigned char *block; /* +block */
unsigned int blockLen; /* length of block */
int +digestAlgorithm; /* message-digest algorithm */

+

+Produces a digest of the data block supplied (pointed to by block, +blockLen bytes long), using the digest algorithm indicated by +digestAlgorithm. On success, the digest is returned in digest, +and the length of the digest is indicated by digestLen. Context +creation, initialisation and clearing is handled internally.

+

+Returns RE_DIGEST_ALGORITHM if an invalid (unsupported) digest algorithm is +selected, IDOK otherwise. + +

+

+MD2Init

+

void MD2Init(context)
MD2_CTX *context; /* context */

+

+Initialises a new MD2 context, ready for digest production. context is +a pointer to a "blank" MD2_CTX structure. + +

+

+MD2Update

+

void MD2Update(context, input, inputLen)
MD2_CTX *context; /* +context */
unsigned char *input; /* input block */
unsigned int +inputLen; /* length of input block */

+

+Updates the MD2 context from the supplied data block (pointed to by +input, inputLen bytes long). context must be an MD2_CTX +structure which has been initialised using MD2_init. No checks are made +for context validity.

+

+ +

+

+MD2Final

+

void MD2Final(digest, context)
unsigned char digest[16]; /* +message digest */
MD2_CTX *context; /* context */

+

+Produces the final MD2 digest value from context. context must +be an MD2_CTX structure which has been initialised using MD2_init. No +checks are made for context validity. On exit, digest contains the MD2 +message digest. MD2Final zeroes the context to remove any sensitive data +from memory. + +

+

+MD4Init

+

void MD4Init(context)
MD4_CTX *context; /* context */

+

+Initialises a new MD4 context, ready for digest production. context is +a pointer to a "blank" MD4_CTX structure. + +

+

+MD4Update

+

void MD4Update(context, input, inputLen)
MD4_CTX *context; /* +context */
unsigned char *input; /* input block */
unsigned int +inputLen; /* length of input block */

+

+Updates the MD4 context from the supplied data block (pointed to by +input, inputLen bytes long). context must be an MD4_CTX +structure which has been initialised using MD4_init. No checks are made +for context validity. + +

+

+MD4Final

+

void MD4Final(digest, context)
unsigned char digest[16]; /* +message digest */
MD4_CTX *context; /* context */

+

+Produces the final MD4 digest value from context. context must +be an MD4_CTX structure which has been initialised using MD4_init. No +checks are made for context validity. On exit, digest contains the MD4 +message digest. MD4Final zeroes the context to remove any sensitive data +from memory. + +

+

+MD5Init

+

void MD5Init (context)
MD5_CTX *context; /* context */

+

+Initialises a new MD5 context, ready for digest production. context is +a pointer to a "blank" MD5_CTX structure. + +

+

+MD5Update

+

void MD5Update(context, input, inputLen)
MD5_CTX *context; /* +context */
unsigned char *input; /* input block */
unsigned int +inputLen; /* length of input block */

+

+Updates the MD5 context from the supplied data block (pointed to by +input, inputLen bytes long). context must be an MD5_CTX +structure which has been initialised using MD5_init. No checks are made +for context validity. + +

+

+MD5Final

+

void MD5Final (digest, context)
unsigned char digest[16]; /* +message digest */
MD5_CTX *context; /* context */

+

+Produces the final MD5 digest value from context. context must +be an MD5_CTX structure which has been initialised using MD5_init. No +checks are made for context validity. On exit, digest contains the MD5 +message digest. MD5Final zeroes the context to remove any sensitive data +from memory. + +

+

+SHSInit

+

void SHSInit(context)
SHS_CTX *context; /* context */

+

+Initialises a new SHS context, ready for digest production. context is +a pointer to a "blank" SHS_CTX structure. + +

+

+SHSUpdate

+

void SHSUpdate(context, buffer, count)
SHS_CTX *context; /* +context */
BYTE *buffer; /* input block */
int count; /* length of +input block */

+

+Updates the SHS context from the supplied data block (pointed to by +buffer, count bytes long). context must be an SHS_CTX +structure which has been initialised using SHS_init. No checks are made +for context validity.

+

+ +

+

+SHSFinal

+

void SHSFinal(digest, context)
char *digest /* digest */
SHS_CTX +*context; /* context */

+

+Produces the final SHS digest value from context, returning the digest +in digest. context must be an SHS_CTX structure which has been +initialised using SHS_init. No checks are made for context validity. On +exit, digest contains the SHS message digest, and context is +cleared.

+

+ +

+
+

+DIGITAL SIGNATURE ROUTINES +

+
    +
  1. Introduction +
  2. +
  3. Functions
      +
    1. R_SignInit +
    2. +
    3. R_SignUpdate +
    4. +
    5. R_SignFinal +
    6. +
    7. R_SignBlock +
    8. +
    9. R_VerifyInit +
    10. +
    11. R_VerifyUpdate +
    12. +
    13. R_VerifyFinal +
    14. +
    15. R_VerifyBlockSignature
  4. +
+

+Introduction

+

RSAEURO provides support for digital signatures using MD2, MD4 and MD5 +digests (to maintain compliance with PKCS #1, SHS cannot be used for digital +signatures, as it produces a 160 bit digest).

+

+Signature generation consists of three basic functions: init, which +initialises the relevant structures and contexts; update, which adds +data to the digest, and final which "tidies up", generates the +final digest value, and encrypts it using the sender's secret key to produce the +signature. To simplify implementation, the signature routines are called via "parent" +routines, with the digest algorithm required passed as a parameter.

+

+High-level functions are provided for processing data which is memory-resident. +These functions handle all memory allocation, initialisation and processing +internally, providing a "one-stop shop" solution. However, as the +data to be processed must be resident in memory, the run-time resource +requirements of these functions are larger than the init-update-final method.

+

+The procedure for producing a digital signature is as follows: +

+
    +
  1. Initialise the signature context by calling R_SignInit. The +message digest type required is passed as a parameter. To maintain PKCS #1 +compatibility, SHS is rejected by R_SignInit as a digest type. +
  2. +
  3. Process the source data a block at a time using R_SignUpdate. +
  4. +
  5. Produce the final signature using R_SignFinal. The sender's +private key is passed as a parameter. RSA is the only algorithm supported for +signatures.
+

An additional function, R_SignBlock, may be used to produce a +signature for memory-resident data.

+

+RSAEURO also provides routines for verifying a supplied signature. The +procedure is as follows: +

+
    +
  1. Initialise the signature context by calling R_VerifyInit. The +message digest type required is passed as a parameter. To maintain PKCS #1 +compatibility, SHS is rejected by R_SignInit as a digest type. +
  2. +
  3. Process the source data a block at a time using R_VerifyUpdate. +
  4. +
  5. Produce the final digest and verify it against a supplied signature using +R_VerifyFinal. The sender's public key is passed as a parameter, to +allow the decryption of the supplied signature. RSA is the only algorithm +supported for signatures.
+

An additional function, R_VerifyBlock, may be used to verify a +signature for memory-resident data. + +

+

+Functions

+

+R_SignInit

+

int R_SignInit(context, digesttype)
R_SIGNATURE_CTX *context; /* +new context */
int digesttype; /* message-digest algorithm */

+

+Initialises a digest context ready for signature production. The +R_SIGNATURE_CTX type is a union structure supporting the different context types +required for each message digest algorithm. context is a pointer to a "blank" +R_SIGNATURE_CTX structure, digesttype indicates the digest algorithm to +be used. Returns RE_DIGEST_ALGORITHM if an invalid digest type is specified +(such as SHS), IDOK otherwise. + +

+

+R_SignUpdate

+

int R_SignUpdate(context, partIn, partInLen)
R_SIGNATURE_CTX +*context; /* context */
unsigned char *partIn; /* next data part */
unsigned +int partInLen; /* length of next data part */

+

+Updates context using the appropriate digest algorithm (as indicated by +the context) with the supplied data (partInLen bytes from +partIn). Returns RE_DIGEST_ALGORITHM if an invalid digest type is +specified (such as SHS), IDOK otherwise. + +

+

+R_SignFinal

+

int R_SignFinal(context, signature, signatureLen, privateKey)
R_SIGNATURE_CTX +*context; /* context */
unsigned char *signature; /* signature */
unsigned +int *signatureLen; /* length of signature */
R_RSA_PRIVATE_KEY +*privateKey; /* signer's RSA private key */

+

+Produces a signature from the supplied context and private key. The digest +value is first calculated using R_DigestFinal and the context, +and this value is then encrypted using RSA with privatekey. The +encrypted value is returned in signature, and the length of the +signature is returned in signatureLen. Returns RE_PRIVATE_KEY if the +private key is invalid, RE_DIGEST_ALGORITHM if an invalid digest type is +specified (such as SHS), IDOK otherwise.

+

+R_SignFinal "restarts" the signature context, ready for +re-use, and clears all sensitive information. + +

+

+R_SignBlock

+

int R_SignBlock(signature, signatureLen, block, +blockLen,digestAlgorithm, privateKey)
unsigned char *signature; /* signature +*/
unsigned int *signatureLen; /* length of signature */
unsigned char +*block; /* block */
unsigned int blockLen; /* length of block */
int +digestAlgorithm; /* message-digest algorithm */
R_RSA_PRIVATE_KEY +*privateKey; /* signer's RSA private key */

+

+Produces a signature for the data block supplied (pointed to by block, +blockLen bytes long). digestAlgorithm indicates the required +message digest algorithm, privateKey is the sender's RSA private key. On +success, returns IDOK, signature contains the generated signature, +signatureLen indicates the length in bytes of the signature. On error, +returns RE_DIGEST_ALGORITHM if an invalid digest algorithm is selected or +RE_PRIVATE_KEY if the private key is invalid. + +

+

+R_VerifyInit

+

int R_VerifyInit(context, digesttype)
R_SIGNATURE_CTX +*context; /* new context */
int digesttype; /* message-digest algorithm */

+

+Initialises context ready for signature verification. The +R_SIGNATURE_CTX type is a union structure supporting the different context types +required for each message digest algorithm. context is a pointer to a "blank" +R_SIGNATURE_CTX structure, digesttype indicates the digest algorithm to +be used. Returns RE_DIGEST_ALGORITHM if an invalid digest type is specified +(such as SHS), IDOK otherwise. + +

+

+R_VerifyUpdate

+

int R_VerifyUpdate(context, partIn, partInLen)
R_SIGNATURE_CTX +*context; /* context */
unsigned char *partIn; /* next data part */
unsigned +int partInLen; /* length of next data part */

+

+Updates context using the appropriate digest algorithm (as indicated by +the context) with the supplied data (partInLen bytes from +partIn). Returns RE_DIGEST_ALGORITHM if an invalid digest type is +specified (such as SHS), IDOK otherwise. + +

+

+R_VerifyFinal

+

int R_VerifyFinal(context, signature, signatureLen, publicKey)
R_SIGNATURE_CTX +*context; /* context */
unsigned char *signature; /* signature */
unsigned +int *signatureLen; /* length of signature */
R_RSA_PRIVATE_KEY +*privateKey; /* signer's RSA public key */

+

+Verifies the supplied signature against the digest produced from the supplied +context. Returns zero for success, RE_LEN if the supplied signature is too long +(greater than MAX_SIGNATURE_LEN), RE_PUBLIC_KEY if the supplied public key +cannot decrypt the signature correctly, RE_SIGNATURE if the message digests do +not match or RE_DIGEST_ALGORITHM if an invalid digest type is specified (such as +SHS). + +

+

+R_VerifyBlockSignature

+

int R_VerifyBlockSignature( block, blockLen, signature, signatureLen,
+ digestAlgorithm, publicKey)
unsigned char *block; +/* block */
unsigned int blockLen; /* length of block */
unsigned char +*signature; /* signature */
unsigned int signatureLen; /* length of +signature */
int digestAlgorithm; /* message-digest algorithm */
R_RSA_PUBLIC_KEY +*publicKey; /* signer's RSA public key */

+

+Verifies the signature of a memory-resident data block (pointed to by +block, blockLen bytes long). digestAlgorithm indicates +the required message digest algorithm, publicKey is the sender's RSA +public key, signature points to the signature to verify and +signatureLen indicates the length of the signature in bytes. +RE_DIGEST_ALGORITHM if an invalid digest algorithm is selected. On success, +returns zero. On error, returns RE_DIGEST_ALGORITHM if an invalid digest +algorithm is selected, RE_LEN if the supplied signature is too long (greater +than MAX_SIGNATURE_LEN), RE_PUBLIC_KEY if the supplied public key cannot decrypt +the signature correctly or RE_SIGNATURE if the message digests do not match. + +

+
+

+ENVELOPE PROCESSING +

+
    +
  1. Introduction +
  2. +
  3. Sealing data in digital envelopes +
  4. +
  5. Opening digital envelopes +
  6. +
  7. Functions
      +
    1. R_SealInit +
    2. +
    3. R_SealUpdate +
    4. +
    5. R_SealFinal +
    6. +
    7. R_OpenInit +
    8. +
    9. R_OpenUpdate +
    10. +
    11. R_OpenFinal
  8. +
+

+Introduction

+

RSAEURO uses the concept of a "digital envelope" for handling +encrypted data. Data is first encrypted using a secret-key algorithm, using a +random session key. The session key is then encrypted using the public keys of +the intended recipients. The encrypted versions of the session key and the +secret-key encrypted message form the digital envelope. "Opening" a +digital envelope requires the decryption of the session key, using the +recipient's private key (assuming the recipient is one of the intended +recipients!), then using the session key to decrypt the message.

+

+RSAEURO provides four varieties of secret-key encryption, all based on the US +Data Encryption Standard (DES): +

+ +

EA_DES_EDE3_CBC is the most secure, and the slowest, method of encryption +supported by RSAEURO. + +

+

+Sealing data in digital envelopes +

+

The procedure for "sealing" data in a digital envelope is as +follows: +

+
    +
  1. Initialise the envelope context, by calling R_SealInit. +R_SealInit generates the random session key and returns the public-key +encrypted versions of the session key (the session key itself, together with +other intermediate data, is stored in the context). The secret-key encryption +method to use is specified as a parameter to R_SealInit. +
  2. +
  3. Process the source data a block at a time, using R_SealUpdate. +
  4. +
  5. "Close" the envelope using R_SealFinal, and clear the +encryption context. +
+

+Opening digital envelopes +

+

The procedure for "opening" a digital envelope is as follows: +

+
    +
  1. Initialise a new envelope context using R_OpenInit. This decrypts +the session key using the recipient's private key, and sets up the context ready +for decryption of the main message. +
  2. +
  3. Process the encrypted data a block at a time using R_OpenUpdate. +
  4. +
  5. Process the final encrypted data block using R_OpenFinal, which +also removes any padding data. +
+

+Functions

+

+R_SealInit

+

int R_SealInit(context, encryptedKeys, encryptedKeyLens, iv, +publicKeyCount,
publicKeys, encryptionAlgorithm, randomStruct
R_ENVELOPE_CTX +*context; /* new context */
unsigned char **encryptedKeys; /* encrypted keys +*/
unsigned int *encryptedKeyLens; /* lengths of encrypted keys */
unsigned +char iv[8]; /* initialization vector */
unsigned int publicKeyCount; /* +number of public keys */
R_RSA_PUBLIC_KEY **publicKeys; /* public keys */
int +encryptionAlgorithm; /* data encryption algorithm */
R_RANDOM_STRUCT +*randomStruct; /* random structure */

+

+Initialises an envelope sealing operation. context points to an +allocated blank R_ENVELOPE_CTX structure and randomStruct points to a +pre-initialised R_RANDOM_STRUCT. encryptionAlgorithm indicates which +method of secret encryption is required (EA_DES_CBC, EA_DES_EDE2_CBC, +EA_DES_EDE3_CBC or EA_DESX_CBC).

+

+R_SealInit uses the random structure to generate a session key +and initialisation vector for the secret-key encryption (DES in CBC mode +requires a 64-bit initialisation vector).

+

+The public keys of the intended recipients are placed in the publicKeys +array, with the total number of public keys indicated by publicKeyCount +(at least one public key must be supplied). An invalid public key results in an +RE_PUBLIC_KEY error, and no further keys will be processed.

+

+On success, returns zero, the encryptedKeys array contains the +public-key encrypted session key (for each supplied public key) and +encryptedKeyLens contains the respective encrypted key lengths. +iv contains the DES initialisation vector.

+

+On error, returns RE_NEED_RANDOM if randomStruct has not been +initialised, RE_PUBLIC_KEY if an invalid public key has been supplied or +RE_ENCRYPTION_ALGORITHM if an invalid encryption algorithm has been selected. + +

+

+R_SealUpdate

+

int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen)
R_ENVELOPE_CTX +*context; /* context */
unsigned char *partOut; /* next encrypted data part +*/
unsigned int *partOutLen; /* length of next encrypted data part */
unsigned +char *partIn; /* next data part */
unsigned int partInLen; /* length of next +data part */

+

+Continues a sealing operation, encrypting a block of data using the supplied +context. context is a R_ENVELOPE_CTX structure which has been +successfully initialised using R_SealInit. partInLen bytes of +partIn are encrypted and returned in partOut. Due to data +padding, some expansion may occur, and partOut should be at least eight +bytes larger than partIn.

+

+Always returns IDOK. + +

+

+R_SealFinal

+

int R_SealFinal(context, partOut, partOutLen)
R_ENVELOPE_CTX +*context; /* context */
unsigned char *partOut; /* last encrypted data part +*/
unsigned int *partOutLen; /* length of last encrypted data part */

+

+Finalises a sealing operation, flushing the context buffer and resetting the +context (to allow further use of the session key if required). context +is the R_ENVELOPE_CTX structure in use for the current sealing operation. On +exit, partOut contains partOutLen bytes to be appended to the +encrypted data (the contents of the context buffer). partOutLen will be +no more than eight. Always returns IDOK.

+

+Note that although the context is restarted, sensitive information is not +cleared. If the context is no longer required, it is the caller's +responsibility to clear it for security. + +

+

+R_OpenInit

+

int R_OpenInit(context, encryptionAlgorithm, encryptedKey, +encryptedKeyLen, iv,
privateKey)
R_ENVELOPE_CTX *context; +/* new context */
int encryptionAlgorithm; /* data encryption algorithm */
unsigned +char *encryptedKey; /* encrypted data encryption key */
unsigned int +encryptedKeyLen; /* length of encrypted key */
unsigned char iv[8]; /* +initialization vector */
R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA +private key */

+

+Initialises an envelope context ready for an "opening" (decryption) +operation. The encrypted session key is decrypted using privateKey, and +placed in the context. The context is then initialised with the initialisation +vector (supplied unencrypted "in" the envelope, and passed to R_OpenInit +as +iv), ready for decryption. encryptionAlgorithm indicates the +encryption algorithm to be used.

+

+On success, returns zero. On error, returns RE_LEN if encryptedKey is +too long (encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN), RE_PRIVATE_KEY if +the private key is invalid (i.e. the correct session key cannot be +retrieved) or RE_ENCRYPTION_ALGORITHM if an invalid encryption algorithm is +selected. + +

+

+R_OpenUpdate

+

int R_OpenUpdate(context, partOut, partOutLen, partIn, partInLen)
R_ENVELOPE_CTX +*context; /* context */
unsigned char *partOut; /* next recovered data part +*/
unsigned int *partOutLen; /* length of next recovered data part */
unsigned +char *partIn; /* next encrypted data part */
unsigned int partInLen; /* +length of next encrypted data part */

+

+Continues an opening operation, decrypting a block of data using the supplied +context. context is a R_ENVELOPE_CTX structure which has been +successfully initialised using R_OpenInit. partInLen bytes of +partIn are decrypted and returned in partOut. Due to data +padding, some expansion may occur, and partOut should be at least eight +bytes larger than partIn.

+

+Always returns IDOK. + +

+

+R_OpenFinal

+

int R_OpenFinal(context, partOut, partOutLen)
R_ENVELOPE_CTX +*context; /* context */
unsigned char *partOut; /* last recovered data part +*/
unsigned int *partOutLen; /* length of last recovered data part */

+

+Finalises an opening operation, flushing the context buffer and re-initialising +the context. context is the R_ENVELOPE_CTX structure in use for the +current opening operation.

+

+On success, returns zero and partOut contains partOutLen bytes +to be appended to the decrypted data (the contents of the context buffer). +partOutLen will be no more than eight. On error, returns RE_KEY if the +session key is invalid.

+

+Note that although the context is restarted, sensitive information is not +cleared. If the context is no longer required, it is the caller's +responsibility to clear it for security. + +

+
+

+PEM FUNCTIONS +

+
    +
  1. Introduction +
  2. +
  3. Functions
      +
    1. R_EncodePEMBlock +
    2. +
    3. R_DecodePEMBlock +
    4. +
    5. R_SignPEMBlock +
    6. +
    7. R_VerifyPEMSignature +
    8. +
    9. R_SealPEMBlock +
    10. +
    11. R_OpenPEMBlock +
    12. +
    13. R_EncryptOpenPEMBlock +
    14. +
    15. R_DecryptOpenPEMBlock
  4. +
+

+Introduction

+

RSAEURO provides a number functions to process data in Privacy Enhanced Mail +(PEM) format, ASCII-encoded according to RFC 1421. In addition to simple +encoding and decoding functions, PEM "versions" of several other +functions are also provided. The following list of PEM functions provides brief +details, and the function descriptions which follow provide more detailed +information. +

+ +

Throughout this section, any reference to "ASCII encoded" should +be read as "ASCII encoded according to RFC 1421", and so on. + +

+

+Functions

+

+R_EncodePEMBlock

+

int R_EncodePEMBlock(encodedBlock, encodedBlockLen, block, blockLen)
unsigned +char *encodedBlock; /* encoded block */
unsigned int *encodedBlockLen; /* +length of encoded block */
unsigned char *block; /* block */
unsigned +int blockLen; /* length of block */

+

+Encodes a block of binary data into ASCII for transmission through 7-bit +channels such as Internet electronic mail. blockLen bytes of +block are encoded and returned in encodedBlock, of length +encodedBlock (in bytes).

+

+Data expansion occurs as four ASCII characters are used to encode three data +bytes. Therefore, the encodedBlock buffer should be allocated at least +33% larger than block.

+

+Always returns IDOK. + +

+

+R_DecodePEMBlock

+

int R_DecodePEMBlock (outbuf, outlength, inbuf, inlength)
unsigned +char *outbuf; /* block */
unsigned int *outlength; /* length of block */
unsigned +char *inbuf; /* encoded block */
unsigned int inlength; /* length of encoded +block */

+

+Decodes a block of ASCII into binary data. Inbuf holds the input data, +inlength indicates the number of ASCII bytes to process, and therefore +must be an integer multiple of four.

+

+On success, returns IDOK and outbuf contains outlength bytes of +decoded data. On error, returns RE_ENCODING in the event of an encoding error +(or if inlength is not an integer multiple of four). + +

+

+R_SignPEMBlock

+

int R_SignPEMBlock( encodedContent, encodedContentLen, +encodedSignature,
encodedSignatureLen, content, +contentLen, recode, digestAlgorithm,
privateKey)
unsigned char +*encodedContent; /* encoded content */
unsigned int *encodedContentLen; /* +length of encoded content */
unsigned char *encodedSignature; /* encoded +signature */
unsigned int *encodedSignatureLen; /* length of encoded +signature */
unsigned char *content; /* content */
unsigned int +contentLen; /* length of content */
int recode; /* recoding flag */
int +digestAlgorithm; /* digest algorithm */
R_RSA_PRIVATE_KEY *privateKey; /* +signer's RSA private key */

+

+Produces a digital signature of the supplied data, and returns a ASCII-encoded +version of the signature. Optionally ASCII-encodes the data block.

+

+Content contains the data to be signed, contentLen indicates the +length of the data. digestAlgorithm indicates the message digest +algorithm to use, privateKey is the signer's RSA private key, used to +encrypt the digest to produce a signature.

+

+If recode is TRUE, the data block (content) is ASCII encoded +following the message digest generation, and the encoded data is returned in +encodedContent, and its length is returned in +encodedContentLen.

+

+On success, returns IDOK, encodedSignature contains the ASCII encoded +signature and encodedSignatureLen indicates the length of the encoded +signature. On error, returns RE_DIGEST_ALGORITHM if an invalid digest algorithm +is specified or RE_PRIVATE_KEY if the private key is invalid. + +

+

+R_VerifyPEMSignature

+

int R_VerifyPEMSignature( content, contentLen, encodedContent, +encodedContentLen,
encodedSignature, +encodedSignatureLen, recode,
digestAlgorithm, +publicKey)
unsigned char *content; /* content */
unsigned int +*contentLen; /* length of content */
unsigned char *encodedContent; /* +(possibly) encoded content */
unsigned int encodedContentLen; /* length of +encoded content */
unsigned char *encodedSignature; /* encoded signature */
unsigned +int encodedSignatureLen; /* length of encoded signature */
int recode; /* +recoding flag */
int digestAlgorithm; /* digest algorithm */
R_RSA_PUBLIC_KEY +*publicKey; /* signer's public key */

+

+Decodes and verifies an ASCII-encoded signature. Optionally decodes the data +block prior to message digest generation and verification.

+

+content contains the data against which the signature is to be verified, +contentLen indicates the length of the data. If recode is TRUE, +encodedContent (encodedContentLen bytes long) is decoded into +content prior to signature verification.

+

+publicKey is used to decrypt the signature, and the resulting message +digest is compared with the digest generated from content using the +digest algorithm indicated by digestAlgorithm (it is the caller's +responsibility to identify the appropriate digest algorithm).

+

+Returns zero for success (the digests match), RE_SIGNATURE_ENCODING if the +signature cannot be decoded correctly, RE_CONTENT_ENCODING if the content cannot +be decoded correctly, RE_LEN if the signature length is invalid, +RE_DIGEST_ALGORITHM if an invalid digest algorithm is selected, RE_PUBLIC_KEY if +the supplied public key is invalid or RE_SIGNATURE if the signature is incorrect +(i.e. the digests do not match). + +

+

+R_SealPEMBlock

+

int R_SealPEMBlock( encryptedContent, encryptedContentLen, +encryptedKey, +
encryptedKeyLen, encryptedSignature, +encryptedSignatureLen, iv,
content, contentLen, +digestAlgorithm, publicKey, privateKey,
randomStruct)
unsigned char +*encryptedContent; /* encoded, encrypted content */
unsigned int +*encryptedContentLen; /* length */
unsigned char *encryptedKey; /* encoded, +encrypted key */
unsigned int *encryptedKeyLen; /* length */
unsigned +char *encryptedSignature; /* encoded, encrypted signature */
unsigned int +*encryptedSignatureLen; /* length */
unsigned char iv[8]; /* DES +initialization vector */
unsigned char *content; /* content */
unsigned +int contentLen; /* length of content */
int digestAlgorithm; /* +message-digest algorithms */
R_RSA_PUBLIC_KEY *publicKey; /* recipient's +RSA public key */
R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key +*/
R_RANDOM_STRUCT *randomStruct; /* random structure */

+

+Seals data in a digital envelope, with EA_DES_CBC encryption and digital +signature, and returns PEM ASCII-encoded data.

+

+content contains the data to be sealed, contentLen indicates the +length of the data. A signature of content is produced using the digest +algorithm indicated by digestAlgorithm and the sender's private key, +privateKey. content is then encrypted using EA_DES_CBC, with a +random session key generated from randomStruct (it is the caller's +responsibility to ensure that randomStruct has been initialised).

+

+On success, returns zero, encryptedContent contains +encryptedContentLen bytes of ASCII encoded encrypted content, +encryptedKey contains the ASCII encoded session key (encryptedKeyLen +bytes long), encrypted with publicKey, and encryptedSignature +contains the ASCII encoded signature. All secret-key encryption is performed +using EA_DES_CBC and the session key.

+

+It is the caller's responsibility to clear the context if it is no longer +required.

+

+On error, returns RE_DIGEST_ALGORITHM if an invalid digest algorithm is +selected, RE_PRIVATE_KEY if the private key is invalid, RE_PUBLIC_KEY if the +public key is invalid or RE_NEED_RANDOM if the random structure is not +initialised. + +

+

+R_OpenPEMBlock

+

int R_OpenPEMBlock( content, contentLen, encryptedContent,
+ encryptedContentLen, encryptedKey, encryptedKeyLen,
+encryptedSignature, encryptedSignatureLen, iv,
digestAlgorithm, +privateKey, publicKey)
unsigned char *content; /* content */
unsigned +int *contentLen; /* length of content */
unsigned char *encryptedContent; /* +encoded, encrypted content */
unsigned int encryptedContentLen; /* length */
unsigned +char *encryptedKey; /* encoded, encrypted key */
unsigned int +encryptedKeyLen; /* length */
unsigned char *encryptedSignature; /* encoded, +encrypted signature */
unsigned int encryptedSignatureLen; /* length */
unsigned +char iv[8]; /* DES initialization vector */
int digestAlgorithm; /* +message-digest algorithms */
R_RSA_PRIVATE_KEY *privateKey; /* recipient's +RSA private key */
R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key +*/

+

+"Opens" a ASCII encoded digital envelope, verifies the signature, +decodes and decrypts the content of the envelope.

+

+encryptedContent contains the encoded, encrypted content, and +encryptedContent indicates its length in bytes. The session key is +retrieved from encryptedKey (encryptedKeyLen bytes long) using +publicKey, then used to decrypt the encryptedContent. Once the +content has been decrypted, the signature is retrieved, decoded and verified +against the content using the recipient's private key (privateKey) and +the message digest algorithm indicated by digestAlgorithm.

+

+On success, returns zero and content contains contentLen bytes +of plaintext data.

+

+On error, returns RE_KEY_ENCODING if the key cannot be decoded, +RE_SIGNATURE_ENCODING if the signature cannot be decoded, RE_CONTENT_ENCODING if +the content cannot be decoded, RE_LEN if the encrypted session key is too long, +RE_PRIVATE_KEY if the private key is invalid, RE_KEY if the retrieved session +key is invalid, RE_DIGEST_ALGORTIHM if an invalid digest algorithm is selected, +RE_PUBLIC_KEY if the public key is invalid or RE_SIGNATURE if the signature is +incorrect (i.e. the message digests do not match). + +

+

+R_EncryptOpenPEMBlock

+

int R_EncryptOpenPEMBlock(context, output, outputLen, input, +inputLen)
R_ENVELOPE_CTX *context; /* context */
unsigned char *output; +/* encrypted, encoded block */
unsigned int *outputLen; /* length of output +*/
unsigned char *input; /* block to encrypt */
unsigned int +inputLen; /* length */

+

+Encrypts a block of data and returns the ciphertext in ASCII encoded format. +context is the current envelope context, which must have been +initialised correctly by the caller. inputLen bytes from input are +encrypted and encoded into ASCII, then returned in output. On exit, +outputLen may be up to 33% larger than inputLen (three source +bytes become four output bytes), so output should be allocated to +account for the data expansion. Always returns IDOK. + +

+

+R_DecryptOpenPEMBlock

+

int R_DecryptOpenPEMBlock(context, output, outputLen, input, +inputLen)
R_ENVELOPE_CTX *context; /* context */
unsigned char *output; +/* decoded, decrypted block */
unsigned int *outputLen; /* length of output +*/
unsigned char *input; /* encrypted, encoded block */
unsigned int +inputLen; /* length */

+

+Decrypts a block of ASCII encoded ciphertext and returns the plaintext in +output. context is the current envelope context, which must +have been initialised correctly by the caller. inputLen bytes from +input are decoded, decrypted, then returned in output. Always +returns IDOK. + +

+
+

+KEY GENERATION AND EXCHANGE +

+
    +
  1. Introduction +
  2. +
  3. RSA Key Generation +
  4. +
  5. Diffie-Hellman key agreement +
  6. +
  7. Functions
      +
    1. R_GeneratePEMKeys +
    2. +
    3. R_GenerateDHParams +
    4. +
    5. R_SetupDHAgreement +
    6. +
    7. R_ComputeDHAgreedKey
  8. +
+

+Introduction

+

RSAEURO contains functions for the generation of RSA key pairs, and for the +exchange of keys using the Diffie-Hellman agreement protocol. This section +describes these functions and their use. + +

+

+RSA Key Generation +

+

A single function, R_GeneratePEMKeys, provides RSA key generation +for RSAEURO. A "prototype key" is passed to the function, indicating +the length of the modulus in bits and the public exponent. Two values are +supported for the public exponent: 3 or "Fermat 4" (65537). A +pre-initialised random structure is required for key generation. + +

+

+Diffie-Hellman key agreement +

+

Diffie-Hellman key agreement provides a method for exchanging session keys +without using RSA. Diffie-Hellman gains its security form the difficulty of +calculating discrete logarithms in a finite field. The procedure for generating +a session key using Diffie-Hellman is as follows: +

+
    +
  1. The Diffie-Hellman parameters are generated using +R_GenerateDHParams, and passed to the relevant parties (this exchange +can take place over an insecure communications path, as knowledge of the +Diffie-Hellman parameters does not assist an attacker). +
  2. +
  3. The two parties wishing to communicate each generate public and private +values using R_SetupDHAgreement, using the agreed on parameters. +
  4. +
  5. Both parties exchange public values, and compute the session key using +R_ComputeDHAgreedKey. +
+

+Functions

+

+R_GeneratePEMKeys

+

int R_GeneratePEMKeys(publicKey, privateKey, protoKey, randomStruct)
R_RSA_PUBLIC_KEY +*publicKey; /* new RSA public key */
R_RSA_PRIVATE_KEY *privateKey; /* new +RSA private key */
R_RSA_PROTO_KEY *protoKey; /* RSA prototype key */
R_RANDOM_STRUCT +*randomStruct; /* random structure */

+

+Generates an RSA public/private key pair, based on the supplied prototype key.

+

+On success, returns zero, with the new public and private keys returned in +publicKey and privateKey.

+

+On error, returns RE_MODULUS_LEN if the modulus length specified in +protoKey is invalid (either less than MIN_RSA_MODULUS_BITS or greater +than MAX_RSA_MODULUS_BITS), RE_NEED_RANDOM if randomStruct has not been +initialised or RE_DATA if a problem occurred generating primes. + +

+

+R_GenerateDHParams

+

int R_GenerateDHParams(params, primeBits, subPrimeBits, randomStruct)
R_DH_PARAMS +*params; /* new Diffie-Hellman parameters */
unsigned int primeBits; /* +length of prime in bits */
unsigned int subPrimeBits; /* length of subprime +in bits */
R_RANDOM_STRUCT *randomStruct; /* random structure */

+

+Generates a set of Diffie-Hellman parameters (prime/modulus and generator). +primeBits indicates the length of the prime required (in bits), and +subPrimeBits indicates the length of a prime "q" that divides +p-1. The resulting Diffie-Hellman "generator" is of order q. randomStruct +points to an initialised random structure.

+

+It is the caller's responsibility to use sensible values for primeBits; +there are no sanity checks.

+

+On success, returns zero, and the Diffie-Hellman parameters in params.

+

+On error, returns RE_NEED_RANDOM if randomStruct has not been +initialised or RE_DATA if a problem occurred generating primes. + +

+

+R_SetupDHAgreement

+

int R_SetupDHAgreement(publicValue, privateValue, privateValueLen, +params,
randomStruct)
unsigned char +*publicValue; /* new public value */
unsigned char *privateValue; /* new +private value */
unsigned int privateValueLen; /* length of private value */
R_DH_PARAMS +*params; /* Diffie-Hellman parameters */
R_RANDOM_STRUCT *randomStruct; /* +random structure */

+

+Generates a set of public and private Diffie-Hellman values, using the supplied +prime and generator (from params).

+

+params is a previously initialised R_DH_PARAMS structure, +randomStruct points to an initialised random structure. +privateValueLen indicates the length of the required private value in +bytes (typically, the same size as the subPrimeBits value supplied to +R_GenerateDHParameters).

+

+On success, returns IDOK, with the Diffie-Hellman private and public values in +privateValue and publicValue respectively (publicValue +is the same length as params->prime).

+

+On error, returns RE_NEED_RANDOM if randomStruct has not been +initialised or RE_DATA if a problem occurred generating primes. + +

+

+R_ComputeDHAgreedKey

+

int R_ComputeDHAgreedKey(agreedKey, otherPublicValue, privateValue, +
privateValueLen, params)
unsigned char +*agreedKey; /* new agreed key */
unsigned char *otherPublicValue; /* other's +public value */
unsigned char *privateValue; /* private value */
unsigned +int privateValueLen; /* length of private value */
R_DH_PARAMS *params; /* +Diffie-Hellman parameters */

+

+Computes a session key from supplied Diffie-Hellman parameters.

+

+params is a previously initialised R_DH_PARAMS structure, +randomStruct points to an initialised random structure. +privateValue points to the caller's Diffie-Hellman private value (privateValueLen +bytes long). OtherPublicValue points to the other party's Diffie-Hellman +public value (which is params->primeLen +long).

+

+On success, returns IDOK, with the generated session key in agreedKey (params->primeLen +bytes long).

+

+On error, returns RE_DATA for a mathematical error (such as incorrect public +values or invalid params structure). + +

+
+

+RSA

+
    +
  1. Introduction +
  2. +
  3. Functions
      +
    1. RSAPrivateEncrypt +
    2. +
    3. RSAPrivateDecrypt +
    4. +
    5. RSAPublicEncrypt +
    6. +
    7. RSAPublicDecrypt
  4. +
+

+Introduction

+

This section describes the RSA processing routines provided by RSAEURO for +RSA encryption and decryption. The RSA functions are listed below: +

+ +
+

NOTE: Paul Kocher recently published a timing-based attack which +could be used against RSA encryption providing the attacker has access to the +machine performing the encryption - this is not usually the case with +email encryption. Future versions of RSAEURO will incorporate protection +against such attacks. For further details, see the preliminary draft of the +paper, available on the Internet at http://www.cryptography.com +and RSADSI's response at http://www.rsa.com. + +

+
+

+Functions

+

+RSAPrivateEncrypt

+

int RSAPrivateEncrypt(output, outputLen, input, inputLen, privateKey)
unsigned +char *output; /* output block */
unsigned int *outputLen; /* length of +output block */
unsigned char *input; /* input block */
unsigned int +inputLen; /* length of input block */
R_RSA_PRIVATE_KEY *privateKey; /* RSA +private key */

+

+Performs a PKCS#1-compliant RSA private-key encryption. inputLen bytes +from input are encrypted using privateKey, and the result +returned in ouput, outputLen bytes long. output should +be large enough to hold the result of the calculation, which will be one byte +longer than the private key (i.e. not larger than MAX_RSA_MODULUS_LEN + +1). inputLen must be at least eleven bytes smaller than the modulus +size (the additional eleven bytes are required for PKCS#1 encoding).

+

+On exit, outputLen bytes of encrypted data are returned in +output. Returns RE_LEN if the input block is too large for the supplied +key, IDOK otherwise. + +

+

+RSAPrivateDecrypt

+

int RSAPrivateDecrypt(output, outputLen, input, inputLen, privateKey)
unsigned +char *output; /* output block */
unsigned int *outputLen; /* length of +output block *
unsigned char *input; /* input block */
unsigned int +inputLen; /* length of input block */
R_RSA_PRIVATE_KEY *privateKey; /* RSA +private key */

+

+Performs an RSA private-key decryption of a PKCS#1-compliant input block. +inputLen bytes from input are decrypted using privateKey, +and the result returned in output, outputLen bytes long. +outputLen will be no larger than MAX_RSA_MODULUS_LEN + 1.

+

+On exit, outputLen bytes of decrypted data are returned in +output. Returns RE_LEN if the input block size is incorrect for the +supplied key, RE_DATA if the decrypted data is not a valid PKCS#1 data block, +IDOK otherwise. + +

+

+RSAPublicEncrypt

+

int RSAPublicEncrypt(output, outputLen, input, inputLen, publicKey,
+ randomStruct)
unsigned char *output; /* output block */
unsigned +int *outputLen; /* length of output block */
unsigned char *input; /* input +block */
unsigned int inputLen; /* length of input block */
R_RSA_PUBLIC_KEY +*publicKey; /* RSA public key */
R_RANDOM_STRUCT *randomStruct; /* random +structure */

+

+Performs a PKCS#1 compliant RSA public key encryption. inputLen bytes +from input are encrypted using publicKey, and the result +returned in ouput, outputLen bytes long. output should +be large enough to hold the result of the calculation, which will be one byte +longer than the public key (i.e. not larger than MAX_RSA_MODULUS_LEN + +1). +inputLen must be at least eleven bytes smaller than the modulus size +(the additional eleven bytes are required for PKCS#1 encoding). +randomStruct must be an initialised random structure (random data is +required for the PKCS#1 data block).

+

+On exit, outputLen bytes of encrypted data are returned in +output. Returns RE_LEN if the input block size is incorrect for the +supplied key, IDOK otherwise.

+

+ +

+

+RSAPublicDecrypt

+

int RSAPublicDecrypt(output, outputLen, input, inputLen, publicKey)
unsigned +char *output; /* output block */
unsigned int *outputLen; /* length of +output block */
unsigned char *input; /* input block */
unsigned int +inputLen; /* length of input block */
R_RSA_PUBLIC_KEY *publicKey; /* RSA +public key */

+

+Performs an RSA public-key decryption of a PKCS#1-compliant input block. +inputLen bytes from input are decrypted using publicKey, +and the result returned in output, outputLen bytes long. +outputLen will be no larger than MAX_RSA_MODULUS_LEN + 1.

+

+On exit, outputLen bytes of decrypted data are returned in +output. Returns RE_LEN if the input block size is incorrect for the +supplied key, RE_DATA if the decrypted data is not a valid PKCS#1 data block, +IDOK otherwise.

+

+ +

+
+

+DES

+
    +
  1. Introduction +
  2. +
  3. Functions
      +
    1. DES_CBCInit +
    2. +
    3. DES_CBCUpdate +
    4. +
    5. DES_CBCRestart +
    6. +
    7. DES3_CBCInit +
    8. +
    9. DES3_CBCRestart +
    10. +
    11. DES3_CBCUpdate +
    12. +
    13. DESX_CBCInit +
    14. +
    15. DESX_CBCRestart +
    16. +
    17. DESX_CBCUpdate
  4. +
+

+Introduction

+

This section describes the core DES processing routines provided by RSAEURO +for DES encryption and decryption in various modes of operation.

+

+RSAEURO supports three different DES modes: single-key DES in +cipher-block-chaining (CBC) mode, three-key DES in CBC mode using "encrypt-decrypt-encrypt" +and DESX, RSADSI's "enhanced" DES (CBC with an additional XOR with a +secret value). Dual-key DES is provided for envelope processing by using +three-key DES with key1 equal to key3.

+

+DES support in each mode consists of three basic functions: init, which +initialises the relevant structure and loads the key (as supplied to the +init function); update, which processes a block of input data +using an initialised context, either encrypting or decrypting, and +restart which restarts a context, resetting the initialisation vector, +allowing the re-use of the same key for further CBC operations.

+

+The context contains the key (in the form of subkeys) during the DES operation, +and as such should be treated as sensitive data. It is the caller's +responsibility to clear the context once the DES operation is complete.

+

+ +

+

+Functions

+

+DES_CBCInit

+

void DES_CBCInit(context, key, iv, encrypt)
DES_CBC_CTX +*context; /* context */
unsigned char *key; /* key */
unsigned char +*iv; /* initializing vector */
int encrypt; /* encrypt flag (1 = encrypt, 0 += decrypt) */

+

+Initialises a DES CBC context, loading the context with the subkeys. +context is a blank DES_CBC_CTX structure, key is the DES key, +iv is the initialising vector and encrypt is a flag indicating +encryption or decryption (zero for decryption, any other value for encryption). +Both key and iv are unsigned char arrays of eight bytes each.

+

+Note that on exit context contains the key supplied, and should be +handled as security sensitive data. It is the caller's responsibility to clear +context once the encryption or decryption operation has been completed.

+

+ +

+

+DES_CBCUpdate

+

int DES_CBCUpdate(context, output, input, len)
DES_CBC_CTX +*context; /* context */
unsigned char *output; /* output block */
unsigned +char *input; /* input block */
unsigned int len;

+

+Continues a DES_CBC operation, encrypting len bytes from input +using the supplied context, placing the results in output. +context must be a DES_CBC_CTX structure which has been initialised using +DES_CBCInit. len must be a multiple of eight bytes. +output must have at least len bytes available.

+

+On exit, output contains len bytes of encrypted data. Returns +RE_LEN if len is not an integer multiple of eight bytes, IDOK otherwise. + +

+

+DES_CBCRestart

+

void DES_CBCRestart(context)
DES_CBC_CTX *context;

+

+Restarts the supplied DES_CBC context, resetting the initialisation vector to +the original value, allowing the use of the same context (and, consequently, the +same DES key) on a new block of data. Note that the key information is not +cleared, so context should be handled as security sensitive data.

+

+ +

+

+DES3_CBCInit

+

void DES3_CBCInit(context, key, iv, encrypt)
DES3_CBC_CTX +*context; /* context */
unsigned char *key; /* key */
unsigned char +*iv; /* initializing vector */
int encrypt; /* encrypt flag (1 = encrypt, 0 += decrypt) */

+

+Initialises an Encrypt-Decrypt-Encrypt (EDE) DES CBC context, loading the +context with the subkeys from the three supplied DES keys. context is a +blank DES3_CBC_CTX structure, key is the DES key, iv is the +initialising vector and encrypt is a flag indicating encryption or +decryption (zero for decryption, any other value for encryption). Both +key and iv are unsigned byte arrays, of twenty-four and eight +bytes respectively (the key array consists of the three DES keys +concatenated).

+

+Note that on exit context contains the key supplied, and should be +handled as security sensitive data. It is the caller's responsibility to clear +context once the encryption or decryption operation has been completed. + +

+

+DES3_CBCRestart

+

void DES3_CBCRestart (context)
DES3_CBC_CTX *context; /* context +*/

+

+Restarts the supplied DES3_CBC context, resetting the initialisation vector to +the original value, allowing the use of the same context (and, consequently, the +same DES key) on a new block of data. Note that the key information is not +cleared, so context should be handled as security sensitive data. + +

+

+DES3_CBCUpdate +

+

int DES3_CBCUpdate(context, output, input, len)
DES3_CBC_CTX +*context; /* context */
unsigned char *output; /* output block */
unsigned +char *input; /* input block */
unsigned int len; /* length of input and +output blocks */

+

+Continues a DES3_CBC operation, encrypting len bytes from input +using the supplied context, placing the results in output. +context must be a DES3_CBC_CTX structure which has been initialised +using DES3_CBCInit. len must be a multiple of eight bytes. +output must have at least len bytes available.

+

+On exit, output contains len bytes of encrypted data. Returns +RE_LEN if len is not an integer multiple of eight bytes, IDOK otherwise. + +

+

+DESX_CBCInit

+

void DESX_CBCInit(context, key, iv, encrypt)
DESX_CBC_CTX +*context; /* context */
unsigned char *key; /* DES key and whiteners */
unsigned +char *iv; /* DES initializing vector */
int encrypt; /* encrypt flag (1 = +encrypt, 0 = decrypt) */

+

+Initialises an DESX CBC context, loading the context with the subkeys and "whiteners" +from the supplied key. context is a blank DESX_CBC_CTX structure, key +is the DESX key (the DES key, input whitener and output whitener concatenated), +iv is the initialising vector and encrypt is a flag indicating +encryption or decryption (zero for decryption, any other value for encryption). +Both key and iv are unsigned byte arrays, of twenty-four and +eight bytes respectively (the key array consists of the three DES keys +concatenated).

+

+Note that on exit context contains the key supplied, and should be +handled as security sensitive data. It is the caller's responsibility to clear +context once the encryption or decryption operation has been completed. + +

+

+DESX_CBCRestart

+

void DESX_CBCRestart(context)
DESX_CBC_CTX *context; /* context +*/

+

+Restarts the supplied DESX_CBC context, resetting the initialisation vector to +the original value, allowing the use of the same context (and, consequently, the +same DES key) on a new block of data. Note that the key information is not +cleared, so context should be handled as security sensitive data. + +

+

+DESX_CBCUpdate +

+

int DESX_CBCUpdate (context, output, input, len)
DESX_CBC_CTX +*context; /* context */
unsigned char *output; /* output block */
unsigned +char *input; /* input block */
unsigned int len; /* length of input and +output blocks */

+

+Continues a DESX_CBC operation, encrypting len bytes from input +using the supplied context, placing the results in output. +context must be a DESX_CBC_CTX structure which has been initialised +using DESX_CBCInit. len must be a multiple of eight bytes. +output must have at least len bytes available.

+

+On exit, output contains len bytes of encrypted data. Returns +RE_LEN if len is not an integer multiple of eight bytes, IDOK otherwise.

+

+ +

+
+

+NATURAL NUMBER ARITHMETIC +

+
    +
  1. Introduction +
  2. +
  3. Representation of natural numbers +
  4. +
  5. Functions
      +
    1. NN_Decode +
    2. +
    3. NN_Encode +
    4. +
    5. NN_Assign +
    6. +
    7. NN_AssignZero +
    8. +
    9. NN_Assign2Exp +
    10. +
    11. NN_Add +
    12. +
    13. NN_Sub +
    14. +
    15. NN_Mult +
    16. +
    17. NN_LShift +
    18. +
    19. NN_RShift +
    20. +
    21. NN_Div +
    22. +
    23. NN_Mod +
    24. +
    25. NN_ModMult +
    26. +
    27. NN_ModExp +
    28. +
    29. NN_ModInv +
    30. +
    31. NN_Gcd +
    32. +
    33. NN_Cmp +
    34. +
    35. NN_Zero +
    36. +
    37. NN_Digits +
    38. +
    39. NN_Bits +
    40. +
    41. GeneratePrime
  6. +
+

+Introduction

+

This section describes the natural number arithmetic "primitives" +used by various functions within RSAEURO. The following table provides brief +details, and the function descriptions which follow provide more detailed +information. +

+ +
+                                                
+
+
+

+Representation of natural numbers +

+

Natural numbers are represented internally in RSAEURO as arbitrary-length +NN_DIGIT arrays, where the NN_DIGIT type is by default an unsigned 32-bit value +(UINT4). The maximum size of an NN_DIGIT array is set by MAX_NN_DIGITS which is +derived from MAX_RSA_MODULUS_LEN, to ensure that all values are generated within +an appropriate range. The mathematical functions effectively treat NN_DIGIT +arrays as integers of an arbitrary length. In the context of natural numbers +within RSAEURO, a "digit" is an NN_DIGIT element of a natural number, +as opposed to the normal meaning (i.e. a single numerical digit). For +example, a ten-digit NN_DIGIT array consists of forty bytes of data (ten +UINT4s).

+

+NN_DIGIT arrays are packed into unsigned character arrays, most significant bit +first, when values are returned to higher-level functions. This behaviour is +primarily to maintain compatibility with existing RSAREF code.

+

+For the remainder of this section, the term "natural number" is used +to describe an NN_DIGIT array. + +

+

+Functions

+

+NN_Decode

+

void NN_Decode (a, digits, b, len)
NN_DIGIT *a;
unsigned char +*b;
unsigned int digits, len;

+

+Decodes a character array into a natural number. b is a pointer to the +character array, which is len bytes long. a is a pointer to the +destination natural number, which is digits digits long.

+

+digits must be large enough to accommodate len bytes; if it is +not, the most significant bytes of a are truncated. + +

+

+NN_Encode

+

void NN_Encode (a, len, b, digits)
NN_DIGIT *b;
unsigned char +*a;
unsigned int digits, len;

+

+Encodes a natural number into a character array. b is a pointer to the +natural number, which is digits digits long. a points to the +destination character array, which is len bytes long.

+

+len must be long enough to accommodate digits digits of b; +if it is not, the most significant digits of the natural number are truncated. + +

+

+NN_Assign

+

void NN_Assign (a, b, digits)
NN_DIGIT *a, *b;
unsigned int +digits;

+

+Assigns a = b, where a and b are natural numbers. Note that +only +digits digits of a are assigned, so if NNDigits(a) > +NNDigits(b), the most significant digits of a will not be cleared. + +

+

+NN_AssignZero

+

void NN_AssignZero (a, digits)
NN_DIGIT *a;
unsigned int +digits;

+

+Zeroises digits digits of the natural number a. + +

+

+NN_Assign2Exp

+

void NN_Assign2Exp (a, b, digits)
NN_DIGIT *a;
unsigned int +b, digits;

+

+Assigns a = 2b. a is the destination natural number which has +digits digits and b is the exponent. The result is undefined if +b is greater than digits&nbsp;*&nbsp;NN_DIGIT_BITS. + +

+

+NN_Add

+

NN_DIGIT NN_Add (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned +int digits;

+

+Computes a = b + c, and returns the carry. a, b, c and +the return value are natural numbers, all digits digits long. + +

+

+NN_Sub

+

NN_DIGIT NN_Sub (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned +int digits;

+

+Computes a = b - c, and returns the borrow. a, b, c and +the return value are natural numbers, all digits digits long. + +

+

+NN_Mult

+

void NN_Mult (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned +int digits;

+

+Computes a = b * c. a, b, c and the return value are +natural numbers, all digits digits long. The result is undefined if +digits > MAX_NN_DIGITS. + +

+

+NN_LShift

+

NN_DIGIT NN_LShift (a, b, c, digits)
NN_DIGIT *a, *b;
unsigned +int c, digits;

+

+Computes a = b * 2c (i.e. shifts b left c bits, +returning the result in a). a, b, c and the +return value are natural numbers, all digits digits long. The result is +undefined if +c > NN_DIGIT_BITS. + +

+

+NN_RShift

+

NN_DIGIT NN_RShift (a, b, c, digits)
NN_DIGIT *a, *b;
unsigned +int c, digits;

+

+Computes a = b div 2c (i.e. shifts b right c bits, returning the result +in a). Returns the carry. a, b, c and the return value +are natural numbers, all digits digits long. The result is undefined if +c > NN_DIGIT_BITS. + +

+

+NN_Div

+

void NN_Div (a, b, c, cDigits, d, dDigits)
NN_DIGIT *a, *b, *c, +*d;
unsigned int cDigits, dDigits;

+

+Computes a = c div d and b = c mod d. a, b, c and d +are natural numbers. a and c are cDigits digits long, +b and d are dDigits digits long. The result is +undefined if d = 0, cDigits >= 2&nbsp;*&nbsp;MAX_NN_DIGITS +or +dDigits > MAX_NN_DIGITS. + +

+

+NN_Mod

+

void NN_Mod (a, b, bDigits, c, cDigits)
NN_DIGIT *a, *b, *c;
unsigned +int bDigits, cDigits;

+

+Computes a = b mod c. a, b, and c are natural numbers. +a and c are cDigits long, b is bDigits +long. The result is undefined if c = 0, bDigits >= 2&nbsp;*&nbsp;MAX_NN_DIGITS +or cDigits > MAX_NN_DIGITS + +

+

+NN_ModMult

+

void NN_ModMult (a, b, c, d, digits)
NN_DIGIT *a, *b, *c, *d;
unsigned +int digits;

+

+Computes a = b * c mod d. a, b, c and d are +natural numbers, all digits digits long. The result is undefined if +d = 0 or digits > MAX_NN_DIGITS. + +

+

+NN_ModExp

+

void NN_ModExp (a, b, c, cDigits, d, dDigits)
NN_DIGIT *a, *b, +*c, *d;
unsigned int cDigits, dDigits;

+

+Computes a = bc mod d. a, b, c and d are natural +numbers. a, b and d are dDigits digits long, +c is cDigits digits long.. The result is undefined if d += 0, cDigits = 0 or dDigits > MAX_NN_DIGITS. + +

+

+NN_ModInv

+

void NN_ModInv (a, b, c, digits)
NN_DIGIT *a, *b, *c;
unsigned +int digits;

+

+Computes a = 1/b mod c. a, b and c are natural numbers, +all digits digits long. The result is undefined if b and +c are not relatively prime (e.g. gcd(b, c) is not 1) or +digits > MAX_NN_DIGITS. + +

+

+NN_Gcd

+

void NN_Gcd(a ,b ,c, digits)
NN_DIGIT *a, *b, *c;
unsigned +int digits;

+

+Calculates the greatest common divisor of b and c, returning the +result in a. a, b and c are natural numbers, all +digits digits long. The result is undefined if c < b +or digits > MAX_NN_DIGITS.

+

+ +

+

+NN_Cmp

+

int NN_Cmp (a, b, digits)
NN_DIGIT *a, *b;
unsigned int +digits;

+

+Compares a and b, returns -1 if a<b, 0 if a=b +or 1 if a>b. . a, b and c are natural +numbers, all digits digits long. + +

+

+NN_Zero

+

int NN_Zero (a, digits)
NN_DIGIT *a;
unsigned int digits;

+

+Returns 1 iff a = 0, otherwise returns 1. a is a natural number, +digits digits long. + +

+

+NN_Digits

+

unsigned int NN_Digits (a, digits)
NN_DIGIT *a;
unsigned int +digits;

+

+Returns the significant length in digits of the natural number a (e.g. +the position of the first non-zero digit). digits is the length of a +in digits. + +

+

+NN_Bits

+

unsigned int NN_Bits (a, digits)
NN_DIGIT *a;
unsigned int +digits;

+

+Returns the significant length in bits of the natural number a (e.g. +the position of the first non-zero bit). digits is the total length of +a in digits. + +

+

+GeneratePrime

+

int GeneratePrime(a, b, c, d, digits, randomStruct)
NN_DIGIT *a, +*b, *c, *d;
unsigned int digits;
R_RANDOM_STRUCT *randomStruct; /* +random structure */

+

+Generates a random probable prime a, where b < a < +c and a-1 is divisible by d. a, b, c +and d are natural numbers, all digits digits long. +randomStruct is an initialised R_RANDOM_STRUCT.

+

+On exit, the generated prime is returned in a. Returns RE_NEED_RANDOM if +randomStruct has not been fully initialised, RE_DATA if a suitable prime +could not be found, IDOK otherwise. + +

+
+

+MEMORY MANIPULATION +

+
    +
  1. Introduction +
  2. +
  3. Functions
      +
    1. R_memset +
    2. +
    3. R_memcpy +
    4. +
    5. R_memcmp
  4. +
+

+Introduction

+

There are three memory manipulation functions used within RSAEURO: +

+ +

All of these routines are "secure", in that no intermediate +storage is used during their operation. + +

+

+Functions

+

+R_memset

+

void R_memset(output, value, len)
POINTER output; /* output block +*/
int value; /* value */
unsigned int len; /* length of block */

+

+Sets len bytes starting at output to value. + +

+

+R_memcpy

+

void R_memcpy(output, input, len)
POINTER output; /* output block +*/
POINTER input; /* input block */
unsigned int len; /* length of +blocks */

+

+Copies len bytes from input to output. + +

+

+R_memcmp

+

int R_memcmp(Block1, Block2, len)
POINTER Block1; /* first block +*/
POINTER Block2; /* second block */
unsigned int len; /* length of +blocks */

+

+Compares len bytes starting at Block1 with Block2.

+

+Returns zero if the blocks are identical. If the blocks are different, returns +the difference between the first two non-identical bytes (returns +Block1[difference] - Block2[difference], where difference is the offset +of the first non-identical byte. + +

+
+

+TECHNICAL INFORMATION +

+
    +
  1. Introduction +
  2. +
  3. Error Types +
  4. +
  5. RSAEURO Data Types
      +
    1. R_RANDOM_STRUCT +
    2. +
    3. R_RSA_PUBLIC_KEY +
    4. +
    5. R_RSA_PRIVATE_KEY +
    6. +
    7. R_RSA_PROTO_KEY +
    8. +
    9. R_DH_PARAMS +
    10. +
    11. R_DIGEST_CTX +
    12. +
    13. R_SIGNATURE_CTX +
    14. +
    15. R_ENVELOPE_CTX +
    16. +
    17. MD2_CTX +
    18. +
    19. MD4_CTX +
    20. +
    21. MD5_CTX +
    22. +
    23. SHS_CTX +
    24. +
    25. DES_CBC_CTX +
    26. +
    27. DESX_CBC_CTX +
    28. +
    29. DES3_CBC_CTX
    30. +
  6. +
  7. Configuration parameters +
  8. +
  9. Platform-specific Configuration
      +
    1. Types +
    2. +
    3. Defined macros
    4. +
  10. +
  11. References
      +
    1. General +
    2. +
    3. RSA +
    4. +
    5. Diffie-Hellman +
    6. +
    7. Digest Algorithms +
    8. +
    9. DES +
    10. +
    11. Privacy-enhanced mail
  12. +
+

+Introduction

+

This section contains miscellaneous technical information regarding RSEURO. +The following subjects are covered: +

+
    +
  1. Error Type. A complete list of RSAEURO error types and possible +explanations. +
  2. +
  3. RSAEURO Data Types A list and brief description of the major +RSAEURO data types. +
  4. +
  5. Platform-specific configuration Platform-specific configuration +information, including compiler settings and data structures. +
  6. +
  7. References Sources of further reading for related subjects and +standards +
+

+Error Types +

+
+RE_CONTENT_ENCODING +
+
An ASCII encoding error occurred during the decoding of a content block.
+
RE_DATA +
+
An error occurred during one of the mathematical routines. Usually caused +by incorrect or invalid data, such as an unmatched set of Diffie-Hellman values.
+
RE_DIGEST_ALGORITHM +
+
An invalid digest algorithm was selected; either an unsupported digest was +selected (i.e. not one of the DA_xx values from RSAEURO.H), or SHS was selected +for signature generation. +
+
RE_ENCODING +
+
An ASCII encoding error occurred during the decoding of a data block.
+
RE_KEY +
+
The recovered session key cannot decrypt the associated content or +signature.
+
RE_KEY_ENCODING +
+
An ASCII encoding error occurred during the decoding of a session key.
+
RE_LEN +
+
An out-of-range signature or session key was encountered, or the data +supplied to an RSA function was too large for the key provided.
+
RE_MODULUS_LEN +
+
An invalid RSA modulus length was specified (either too long or too short.
+
RE_NEED_RANDOM +
+
An attempt was made to generate random data using an uninitialised random +structure.
+
RE_PRIVATE_KEY +
+
The supplied private key was invalid/incorrect.
+
RE_PUBLIC_KEY +
+
The supplied public key was invalid/incorrect.
+
RE_SIGNATURE +
+
The signature does not match the associated data block.
+
RE_SIGNATURE_ENCODING +
+
An ASCII encoding error occurred during the decoding of a signature.
+
RE_ENCRYPTION_ALGORITHM +
+
An invalid encryption algorithm was specified. + +
+

+RSAEURO Data Types +

+

+R_RANDOM_STRUCT

+

typedef struct {
unsigned int bytesNeeded; /* seed bytes +required */
unsigned char state[16]; /* state of object */
unsigned +int outputAvailable; /* number byte available */
unsigned char +output[16]; /* output bytes */
} R_RANDOM_STRUCT;

+

+The R_RANDOM_STRUCT type stores the state and characteristics of a random number +generator. bytesNeeded Number of remaining "mix in" bytes required to +initialise the structure (initially defined by RANDOM_BYTES_RQ). Must be zero +before the structure may be used.

+

+state Internal state of the random number generator.

+

+outputAvailable Indicates the number of unused bytes in the output +array. When this value reaches zero, the output array is regenerated.

+

+output Output of the random number generator. + +

+

+R_RSA_PUBLIC_KEY

+

typedef struct {
unsigned int bits; /* length in bits of +modulus */
unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
+unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
} +R_RSA_PUBLIC_KEY;

+

+The R_RSA_PUBLIC_KEY type stores an RSA public key. bits The length of the +modulus in bits (MIN_RSA_MODULUS_BITS < bits £ MAX_RSA_MODULUS_BITS).

+

+modulus The modulus, stored as a MAX_RSA_MODULUS_LEN byte number, most +significant byte first, padded with zero bytes.

+

+exponent The public exponent, stored in the same manner as the modulus. + +

+

+R_RSA_PRIVATE_KEY

+

typedef struct {
unsigned int bits; /* length in bits of +modulus */
unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
+unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
+unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */
+unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */
unsigned +char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */
unsigned +char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */
} +R_RSA_PRIVATE_KEY;

+

+The R_RSA_PRIVATE_KEY type stores an RSA private key. bits The length of the +modulus in bits (MIN_RSA_MODULUS_BITS < bits £ MAX_RSA_MODULUS_BITS).

+

+modulus The modulus, stored as a MAX_RSA_MODULUS_LEN byte number, most +significant byte first, zero padded.

+

+publicExponent The public exponent, stored in the same manner as the +modulus.

+

+exponent The private exponent, stored in the same manner as the modulus.

+

+prime The prime factors (p and q) of the modulus, stored as two +MAX_RSA_PRIME_LEN long numbers in the same manner as the modulus (p&nbsp;>&nbsp;q).

+

+primeExponent The exponents for Chinese Remainder Theorem operations (d +mod p-1 and d&nbsp;mod&nbsp;q-1), stored in the same manner as prime.

+

+coefficient The coefficient (1/q mod p) for Chinese Remainder Theorem +operations, stored in the same manner as prime. + +

+

+R_RSA_PROTO_KEY

+

typedef struct {
unsigned int bits; /* length in bits of +modulus */
int useFermat4; /* public exponent (1 = F4, 0 = 3) */
} +R_RSA_PROTO_KEY;

+

+The R_RSA_PROTO_KEY type provides a template for RSA keypair generation. +bits Length of the modulus in bits (MIN_RSA_MODULUS_BITS < bits < +MAX_RSA_MODULUS_BITS).

+

+useFermat4 Public exponent, either Fermat4 or 3. + +

+

+R_DH_PARAMS

+

typedef struct {
unsigned char *prime; /* prime */
+unsigned int primeLen; /* length of prime */
unsigned char *generator; /* +generator */
unsigned int generatorLen; /* length of generator */
} +R_DH_PARAMS;

+

+The R_DH_PARAMS type stores a set of parameters for a Diffie-Hellman key +exchange. prime The prime p, stored as a primeLen-byte long number, most +significant byte first, zero padded.

+

+primeLen The length in bytes of prime.

+

+generator The generator g, stored in the same manner as prime.

+

+generatorLen The length in bytes of generator. + +

+

+R_DIGEST_CTX

+

typedef struct {
int digestAlgorithm; /* digest type */
+union { /* digest sub-context */
MD2_CTX md2;
MD4_CTX md4;
+MD5_CTX md5;
SHS_CTX shs;
} context;
} R_DIGEST_CTX;

+

+The R_DIGEST_CTX type stores the context for a message digest generation. +digestAlgorithm The message digest algorithm for the context (DA_MD2, DA_MD4, +DA_MD5 or DA_SHS).

+

+context The algorithm-specific context + +

+

+R_SIGNATURE_CTX

+

typedef struct {
R_DIGEST_CTX digestContext;
} +R_SIGNATURE_CTX;

+

+The R_SIGNATURE_CTX type stores the context for a signature generation. +Currently, R_SIGNATUR_CTX is the same as R_DIGEST_CTX, although it has been +separately typed for future revisions. + +

+

+R_ENVELOPE_CTX

+

typedef struct {
int encryptionAlgorithm; /* encryption type */
+union { /* encryption sub-context */
DES_CBC_CTX des;
+DES3_CBC_CTX des3;
DESX_CBC_CTX desx;
} cipherContext;
+unsigned char buffer[8]; /* data buffer */
unsigned int bufferLen; /* +buffer length */
} R_ENVELOPE_CTX;

+

+The R_ENVELOPE_CTX type stores the context for a "sealing" +(encryption) operation. encryptionAlgorithm The encryption algorithm for the +context (EA_DES_CBC, EA_DES_EDE2_CBC, EA_DES_EDE3_CBC or EA_DESX_CBC).

+

+cipherContext The cipher-specific context.

+

+buffer The input buffer for the sealing operation (DES encrypts in +64-bit blocks, so incoming data is buffered until 8 bytes are available).

+

+bufferLen The number of bytes in the buffer. + +

+

+MD2_CTX

+

typedef struct {
unsigned char state[16]; /* state */
+unsigned char checksum[16]; /* checksum */
unsigned int count; /* number +of bytes, modulo 16 */
unsigned char buffer[16]; /* input buffer */
} +MD2_CTX;

+

+The MD2_CTX type stores the context for an MD2 operation. state Internal state +machine.

+

+checksum Checksum (see MD2 source for details).

+

+count Number of bytes processed, modulo 16.

+

+buffer Input buffer for data to be processed. + +

+

+MD4_CTX

+

typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 +count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char +buffer[64]; /* input buffer */
} MD4_CTX

+

+The MD4_CTX type stores the context for an MD4 operation. state Internal state +machine.

+

+count Number of bits processed, modulo 264

+

+buffer Input buffer for data to be processed. + +

+

+MD5_CTX

+

typedef struct {
UINT4 state[4]; /* state (ABCD) */
+UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned +char buffer[64]; /* input buffer */
} MD5_CTX;

+

+The MD5_CTX type stores the context for an MD5 operation. state Internal state +machine.

+

+count Number of bits processed, modulo 264

+

+buffer Input buffer for data to be processed. + +

+

+SHS_CTX

+

typedef struct {
UINT4 digest [5]; /* Message digest */
+UINT4 countLo, countHi; /* 64-bit bit count */
UINT4 data [16]; /* SHS +data buffer */
} SHS_CTX;

+

+The SHS_CTX type stores the context for an MD5 operation. state Internal state +machine.

+

+countLo Number of bits processed, least significant part.

+

+countHi Number of bits processed, most significant part.

+

+data Input buffer for data to be processed. + +

+

+DES_CBC_CTX

+

typedef struct {
UINT4 subkeys[32]; /* subkeys */
UINT4 +iv[2]; /* initializing vector */
UINT4 originalIV[2]; /* for restarting +the context */
int encrypt; /* encrypt flag */
} DES_CBC_CTX;

+

+The DES_CBC_CTX type stores the context for an single-key DES CBC operation. +subkeys Array of DES subkeys, ordered according to initialisation (in "normal" +order for encryption, "reverse" order for decryption).

+

+iv 64-bit initialising vector (current state).

+

+originalIV 64-bit initialising vector (initial state).

+

+encrypt "Direction" indicator; one for encrypt, zero for +decrypt. + +

+

+DESX_CBC_CTX

+

typedef struct {
UINT4 subkeys[32]; /* subkeys */
UINT4 +iv[2]; /* initializing vector */
UINT4 inputWhitener[2]; /* input whitener +*/
UINT4 outputWhitener[2]; /* output whitener */
UINT4 +originalIV[2]; /* for restarting the context */
int encrypt; /* encrypt +flag */
} DESX_CBC_CTX;

+

+The DESX_CBC_CTX type stores the context for an single-key DESX CBC operation. +subkeys Array of DES subkeys, ordered according to initialisation (in "normal" +order for encryption, "reverse" order for decryption).

+

+iv 64-bit initialising vector (current state).

+

+inputWhitener 64-bit input "whitener", XORed with data during +encryption.

+

+outputWhitener 64-bit input "whitener", XORed with data during +encryption.

+

+originalIV 64-bit initialising vector (initial state).

+

+encrypt "Direction" indicator; one for encrypt, zero for +decrypt. + +

+

+DES3_CBC_CTX

+

typedef struct {
UINT4 subkeys[3][32]; /* subkeys for three +operations */
UINT4 iv[2]; /* initializing vector */
UINT4 +originalIV[2]; /* for restarting the context */
int encrypt; /* encrypt +flag */
} DES3_CBC_CTX;

+

+The DES3_CBC_CTX type stores the context for an triple-key DES CBC operation. +subkeys Two-dimensional array of DES subkeys, ordered according to +initialisation (in "normal" order for encryption, "reverse" +order for decryption).

+

+iv 64-bit initialising vector (current state).

+

+originalIV 64-bit initialising vector (initial state).

+

+encrypt "Direction" indicator; one for encrypt, zero for +decrypt. + +

+

+Configuration parameters +

+

The following table describes some of the values defined in the RSAEURO +toolkit header files which may be modified to customise the behaviour of certain +routines. Although the toolkit has been designed with portability in mind, no +guarantee is made that the code will work with different settings - please +report any difficulties. +

+
+Parameter                    Defined in     Description                       Default       
+                                                                              value         
+MIN_RSA_MODULUS_BITS         RSAEURO.H      Minimum size permitted for RSA    508 bits      
+                                            modulus.                                        
+MAX_RSA_MODULUS_BITS         RSAEURO.H      Maximum size permitted for RSA    1024 bits     
+                                            modulus.  (Note: change this                    
+                                            value to allow the use of                       
+                                            larger keys etc)                                
+MAX_DIGEST_LEN               RSAEURO.H      Maximum digest size, in bytes,    20 bytes      
+                                            for any of the supported          (SHS)         
+                                            algorithms.                                     
+RSAEURO_VER_MAJ              RSAEURO.H      Major version number of the       1             
+                                            toolkit.                                        
+RSAEURO_VER_MIN              RSAEURO.H      Minor version number of the       03            
+                                            toolkit.                                        
+RSAEURO_IDENT                RSAEURO.H      Identifier string for the         RSAEURO       
+                                            toolkit (to support variants)                   
+RSAEURO_DATE                 RSAEURO.H      Release date of the major         21/08/94      
+                                            version of the toolkit.                         
+NN_DIGIT                     NN.H           Type for natural number "digit"   UINT4         
+                                                                              (32-bit       
+                                                                              word)         
+NN_DIGIT_BITS                NN.H           Number of bits in an NN_DIGIT     32            
+MAX_NN_DIGIT                 RSAEURO.H      Maximum permitted value for an    0xFFFFFFFF    
+                                            NN_DIGIT                                        
+RANDOM_BYTES_RQ              R_RANDOM.C     Number of random bytes required   256           
+                                            to "seed" a random structure                    
+                                            prior to use.                                   
+RANDOM_BYTES_RQINT           R_RANDOM.C     Number of random bytes from       512           
+                                            ANSI time functions required to                 
+                                            "seed" a random structure prior                 
+                                            to use.                                         
+SHS_BLOCKSIZE                SHS.H          SHS block size, in bytes.         60            
+SHS_DIGESTSIZE               SHS.H          SHS digest size, in bytes.        20            
+
+
+

+Platform-specific Configuration +

+

+Types

+

There are three platform-specific types used in RSAEURO, defined in GLOBAL.H +and described in the following paragraphs. POINTER A generic pointer to memory. +It should be possible to cast any other pointer to POINTER.

+

+BYTE An 8-bit byte.

+

+UINT2 A 16-bit unsigned integer.

+

+UINT4 A 32-bit unsigned integer. + +

+

+Defined macros +

+

RSAEURO uses three #defined macros: +

+ +

+References

+

+General

+

For general information about cryptography and its applications, consult the +following: +

+ +

+RSA

+

For further details of the RSA algorithm, consult the following: +

+ +

+Diffie-Hellman

+

For further details of the Diffie-Hellman key exchange algorithm, consult +the following: +

+ +

+Digest Algorithms +

+

For further details of the digest algorithms used in RSAEURO, consult the +following: +

+ +

+DES

+

For further details of the Data Encryption Standard, consult the following: +

+ +

+Privacy-enhanced mail +

+

For further details of Internet privacy-enhanced mail and its applications, +consult the following: +

+ +
+

+APPENDIX A: FUNCTION CROSS-REFERENCE +

+

This section provides a cross-reference for each function, indicating where +it is described in the documentation. The functions are listed in alphabetical +order. +

+

DES3_CBCInit +

+

DES3_CBCRestart +

+

DES3_CBCUpdate +

+

DES3_CBCInit +

+

DES3_CBCRestart +

+

DES3_CBCUpdate +

+

DESX_CBCInit +

+

DESX_CBCRestart +

+

DESX_CBCUpdate +

+

GeneratePrime +

+

MD2Final +

+

MD2Init +

+

MD2Update +

+

MD4Final +

+

MD4Init +

+

MD4Update +

+

MD5Final +

+

MD5Init +

+

MD5Update +

+

NN_Add +

+

NN_Assign +

+

NN_Assign2Exp +

+

NN_AssignZero +

+

NN_Cmp +

+

NN_Decode +

+

NN_Digits +

+

NN_Div +

+

NN_Encode +

+

NN_Gcd +

+

NN_LShift +

+

NN_Mod +

+

NN_ModExp +

+

NN_ModInv +

+

NN_ModMult +

+

NN_Mult +

+

NN_RShift +

+

NN_Sub +

+

NN_Zero +

+

R_ComputeDHAgreedKey +

+

R_DecodePEMBlock +

+

R_DecryptOpenPEMBlock +

+

R_DigestBlock +

+

R_DigestBlock +

+

R_DigestInit +

+

R_DigestUpdate +

+

R_EncodePEMBlock +

+

R_EncryptOpenPEMBlock +

+

R_GenerateBytes +

+

R_GenerateDHParams +

+

R_GeneratePEMKeys +

+

R_GetRandomBytesNeeded +

+

R_memcmp +

+

R_memcpy +

+

R_memset +

+

R_OpenFinal +

+

R_OpenInit +

+

R_OpenPEMBlock +

+

R_OpenUpdate +

+

R_RandomCreate +

+

R_RandomFinal +

+

R_RandomInit +

+

R_RandomMix +

+

R_RandomUpdate +

+

R_SealFinal +

+

R_SealInit +

+

R_SealPEMBlock +

+

R_SealUpdate +

+

R_SetupDHAgreement +

+

R_SignBlock +

+

R_SignFinal +

+

R_SignInit +

+

R_SignPEMBlock +

+

R_SignUpdate +

+

R_VerifyBlockSignature +

+

R_VerifyFinal +

+

R_VerifyInit +

+

R_VerifyPEMSignature +

+

R_VerifyUpdate +

+

RSAPrivateDecrypt +

+

RSAPrivateEncrypt +

+

RSAPublicDecrypt +

+

RSAPublicEncrypt +

+

SHSFinal +

+

SHSInit +

+

SHSUpdate

+

+

diff --git a/docs/rsaedoc.ps b/docs/rsaedoc.ps new file mode 100644 index 0000000..4a9d31a Binary files /dev/null and b/docs/rsaedoc.ps differ diff --git a/docs/rsaeuro.asc b/docs/rsaeuro.asc old mode 100755 new mode 100644 diff --git a/docs/rsaeuro.ps b/docs/rsaeuro.ps deleted file mode 100755 index 04d79c6..0000000 Binary files a/docs/rsaeuro.ps and /dev/null differ diff --git a/docs/rsaread.me b/docs/rsaread.me old mode 100755 new mode 100644 index d71ab88..908c51c --- a/docs/rsaread.me +++ b/docs/rsaread.me @@ -1,19 +1,19 @@ - RSAEURO Version 1.02 Distribution. - -Well Here it is, this is the RSAEURO Version 1.02 Distribrution. It has -been a year in the making and it is finally here. RSAEURO is a International RSAREF -Replacement written with the intent of producing a package to allow use of -existing RSAREF reliant packages internationally with out the US RSAREF -Restrictions. - -RSAEURO is based about RSAREF II and covers most of the routines in that -package, however there have been some addtions. These include MD4, SHS -and enhanced Random Number routines. - -Enclosed in this distribution is the following. - -RSAEURO.ZIP - RSAEURO Source and Docs in Zip format -RSAEURO.TAZ - RSAEURO Source and Docs in tar/gzip format. - -Please send any comments and/or suggestions to skapp@cix.compulink.co.uk, -you can encrypt these using the RSAEURO public key enclosed within. + RSAEURO Version 1.03 Distribution. + +Well Here it is, this is the RSAEURO Version 1.03 Distribrution. It has +been a year in the making and it is finally here. RSAEURO is a International +RSAREF Replacement written with the intent of producing a package to allow +use of existing RSAREF reliant packages internationally with out the +US RSAREF Restrictions. + +RSAEURO is based about RSAREF II and covers most of the routines in that +package, however there have been some addtions. These include MD4, SHS +and enhanced Random Number routines. + +Enclosed in this distribution is the following. + +RSAEURO.ZIP - RSAEURO Source and Docs in Zip format +RSAEURO.TAZ - RSAEURO Source and Docs in tar/gzip format. + +Please send any comments and/or suggestions to rsaeuro@sourcery.demon.co.uk, +you can encrypt these using the RSAEURO public key enclosed within. diff --git a/docs/scripts.ps b/docs/scripts.ps old mode 100755 new mode 100644 index c3f533e..9b31e75 Binary files a/docs/scripts.ps and b/docs/scripts.ps differ diff --git a/docs/scripts.txt b/docs/scripts.txt old mode 100755 new mode 100644 diff --git a/docs/todo b/docs/todo old mode 100755 new mode 100644 index 4ba6cdc..d1f6c02 --- a/docs/todo +++ b/docs/todo @@ -14,5 +14,5 @@ Well Heres the stuff I have to do. * GSS-API - +* X.509 Certificates diff --git a/install/msdos/makefile.bcc b/install/msdos/makefile.bcc old mode 100755 new mode 100644 index 0d902c4..c410839 --- a/install/msdos/makefile.bcc +++ b/install/msdos/makefile.bcc @@ -1,94 +1,94 @@ -# This is a MAKEFILE for Borland C++ Make - -# extension for object files -O = obj - -# commands -CC = bcc -LIB = tlib - -# name of temporary library script -TEMPFILE = $(TEMP)\temp.mak - -# The places to look for include files (in order). -INCL = -I. -I$(RSAEURODIR) - -# There are no assembler routines for TASM/MASM -# You do have choice to use ansi or not. - -ANSISTD = 0 - -# Utility routines. -del = del -COPY = copy - -# Normal C flags. -# Change -3 to use non 386 instructions. -#CFLAGS = -3 -ml -f- -O -d $(INCL) -c -#CFLAGSx = -3 -ml -f- -O -d $(INCL) - -# Use ANSI ? -# Change -3 to use non 386 instructions. -CFLAGS = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) -c -CFLAGSx = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) - -# The location of the common source directory. -RSAEURODIR = ..\source\# - -RSAEUROLIB = rsaeuro.lib - -RSAREFLIB = rsaref.lib - -# The location of the demo source directory. -DEMODIR = ..\demo\# - -all : $(RSAEUROLIB) demo - -$(RSAREFLIB) : $(RSAEUROLIB) - $(COPY) $(RSAEUROLIB) $(RSAREFLIB) - -demo : redemo mdemo randemo - -randemo : randemo.$(O) $(RSAEUROLIB) - $(CC) $(CFLAGSx) randemo.$(O) $(RSAEUROLIB) - -mdemo : mdemo.$(O) $(RSAEUROLIB) - $(CC) $(CFLAGSx) mdemo.$(O) $(RSAEUROLIB) - -redemo : redemo.$(O) $(RSAEUROLIB) - $(CC) $(CFLAGSx) redemo.$(O) $(RSAEUROLIB) - -$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O)\ - rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O)\ - r_stdlib.$(O) rsa.rsp - @if NOT EXIST $@ $(LIB) $@ - @$(LIB) $(RSAEUROLIB) /C /E @rsa.rsp - -randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h - $(CC) $(CFLAGS) $(DEMODIR)randemo.c - -mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h - $(CC) $(CFLAGS) $(DEMODIR)mdemo.c - -redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h - $(CC) $(CFLAGS) $(DEMODIR)redemo.c - -rsa.rsp : - copy &&| --+desc.obj & --+md2c.obj & --+md4c.obj & --+shsc.obj & --+md5c.obj & --+nn.obj & --+prime.obj & --+rsa.obj & --+r_dh.obj & --+r_encode.obj & --+r_enhanc.obj & --+r_keygen.obj & --+r_random.obj & --+r_stdlib.obj -| rsa.rsp - -!INCLUDE $(RSAEURODIR)targets.mak +# This is a MAKEFILE for Borland C++ Make + +# extension for object files +O = obj + +# commands +CC = bcc +LIB = tlib + +# name of temporary library script +TEMPFILE = $(TEMP)\temp.mak + +# The places to look for include files (in order). +INCL = -I. -I$(RSAEURODIR) + +# There are no assembler routines for TASM/MASM +# You do have choice to use ansi or not. + +ANSISTD = 0 + +# Utility routines. +del = del +COPY = copy + +# Normal C flags. +# Change -3 to use non 386 instructions. +#CFLAGS = -3 -ml -f- -O -d $(INCL) -c +#CFLAGSx = -3 -ml -f- -O -d $(INCL) + +# Use ANSI ? +# Change -3 to use non 386 instructions. +CFLAGS = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) -c +CFLAGSx = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) + +# The location of the common source directory. +RSAEURODIR = ..\source\# + +RSAEUROLIB = rsaeuro.lib + +RSAREFLIB = rsaref.lib + +# The location of the demo source directory. +DEMODIR = ..\demo\# + +all : $(RSAEUROLIB) demo + +$(RSAREFLIB) : $(RSAEUROLIB) + $(COPY) $(RSAEUROLIB) $(RSAREFLIB) + +demo : redemo mdemo randemo + +randemo : randemo.$(O) $(RSAEUROLIB) + $(CC) $(CFLAGSx) randemo.$(O) $(RSAEUROLIB) + +mdemo : mdemo.$(O) $(RSAEUROLIB) + $(CC) $(CFLAGSx) mdemo.$(O) $(RSAEUROLIB) + +redemo : redemo.$(O) $(RSAEUROLIB) + $(CC) $(CFLAGSx) redemo.$(O) $(RSAEUROLIB) + +$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O)\ + rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O)\ + r_stdlib.$(O) rsa.rsp + @if NOT EXIST $@ $(LIB) $@ + @$(LIB) $(RSAEUROLIB) /C /E @rsa.rsp + +randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)randemo.c + +mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)mdemo.c + +redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)redemo.c + +rsa.rsp : + copy &&| +-+desc.obj & +-+md2c.obj & +-+md4c.obj & +-+shsc.obj & +-+md5c.obj & +-+nn.obj & +-+prime.obj & +-+rsa.obj & +-+r_dh.obj & +-+r_encode.obj & +-+r_enhanc.obj & +-+r_keygen.obj & +-+r_random.obj & +-+r_stdlib.obj +| rsa.rsp + +!INCLUDE $(RSAEURODIR)targets.mak diff --git a/install/msdos/makefile.wat b/install/msdos/makefile.wat new file mode 100644 index 0000000..63457e6 --- /dev/null +++ b/install/msdos/makefile.wat @@ -0,0 +1,152 @@ +# This is a makefile for watcom compatible make. +# This seems to work with Version 10.5 of Watcom C/C++ +# It produces DOS4GW executables and character mode Watcom NT executables + +# extension for object files +O = obj + +# commands +CC = wcc386 +LIB = wlib +ASM = as + +# name of temporary library script +TEMPFILE = $(TEMP)\temp.mak + +# Watcom Standard include directory, change to suit +STDINCDIR = \watcom\include + +# The places to look for include files (in order). +INCL = -i. -I$(RSAEURODIR) -I$(STDINCDIR) + +# Extra Defs + +# To select CPU type set CPUT to any of the following +# +# 386 = i386+ processor, 80386 and above processor +# 68k = M680x0 series processor. +# +# Leave empty to disable assembler routines. +# Not Used in Watcom Version. +# CPUT = 386 + +# Set to 1 for ANSI Standard Routine to be Used, only availible +# if assembler routines not it use. +# Dosn't seem to work with Watcom ?? +# ANSISTD = 1 + +# utility routines +del = del +COPY = copy + +# name of main executable to build +PROG = all + +# Standard DOS4GW Executable Flags. Change -3s to -4s for i486 +CFLAGS = $(INCL) -3s -zq -ox -r -sg -zm -zdf -dPROTOTYPES=0 + +# Windows Win32 Executable Flags, works for 10.5 +# CFLAGS = $(INCL) -4s -zq -ox -r -sg -dPROTOTYPES=0 + +ASMFL = $(INCL) -c -Wa,-L +MFLAGS = -I. -I$(RSAEURODIR) + +# The location of the common source directory. +RSAEURODIR = ..\source\ +RSAEUROLIB = rsaeuro.lib +RSAREFLIB = rsaref.lib + +# The location of the demo source directory. +DEMODIR = ..\demo\ + +all : demo $(RSAREFLIB) + +$(RSAREFLIB) : $(RSAEUROLIB) + $(COPY) $(RSAEUROLIB) $(RSAREFLIB) + +demo : redemo mdemo randemo + +randemo.exe : randemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 randemo.$(O) $(RSAEUROLIB) + del *.$(O) + +mdemo.exe : mdemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 mdemo.$(O) $(RSAEUROLIB) + del *.$(O) + +redemo.exe : redemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 redemo.$(O) $(RSAEUROLIB) + del *.$(O) + +$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O) rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O) r_stdlib.$(O) + $(LIB) -n $@ @rsa.wat + +randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)randemo.c + +mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)mdemo.c + +redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)redemo.c + +desc.$(O) : $(RSAEURODIR)desc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)des.h + $(CC) $(CFLAGS) $(RSAEURODIR)desc.c + echo -+$@ > rsa.wat + +shsc.$(O) : $(RSAEURODIR)shsc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)shs.h + $(CC) $(CFLAGS) $(RSAEURODIR)shsc.c + echo -+$@ >> rsa.wat + +md2c.$(O) : $(RSAEURODIR)md2c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md2.h + $(CC) $(CFLAGS) $(RSAEURODIR)md2c.c + echo -+$@ >> rsa.wat + +md4c.$(O) : $(RSAEURODIR)md4c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md4.h + $(CC) $(CFLAGS) $(RSAEURODIR)md4c.c + echo -+$@ >> rsa.wat + +md5c.$(O) : $(RSAEURODIR)md5c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)md5c.c + echo -+$@ >> rsa.wat + +nn.$(O) : $(RSAEURODIR)nn.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)nn.c + echo -+$@ >> rsa.wat + +prime.$(O) : $(RSAEURODIR)prime.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)prime.c + echo -+$@ >> rsa.wat + +rsa.$(O) : $(RSAEURODIR)rsa.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)rsa.c + echo -+$@ >> rsa.wat + +r_dh.$(O) : $(RSAEURODIR)r_dh.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_dh.c + echo -+$@ >> rsa.wat + +r_encode.$(O) : $(RSAEURODIR)r_encode.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_encode.c + echo -+$@ >> rsa.wat + +r_enhanc.$(O) : $(RSAEURODIR)r_enhanc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_enhanc.c + echo -+$@ >> rsa.wat + +r_keygen.$(O) : $(RSAEURODIR)r_keygen.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_keygen.c + echo -+$@ >> rsa.wat + +r_random.$(O) : $(RSAEURODIR)r_random.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_random.c + echo -+$@ >> rsa.wat + +r_stdlib.$(O) : $(RSAEURODIR)r_stdlib.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_stdlib.c + echo -+$@ >> rsa.wat + +# Dependencies for header files + +$(RSAREDIR)rsaeuro.h : $(RSAEURODIR)shs.h $(RSAEURODIR)nn.h $(RSAEURODIR)md2.h $(RSAEURODIR)md5.h $(RSAEURODIR)des.h $(RSAEURODIR)global.h + diff --git a/install/readme.txt b/install/readme.txt new file mode 100644 index 0000000..37b8b12 --- /dev/null +++ b/install/readme.txt @@ -0,0 +1,13 @@ +The makefiles in the directories below + +UNIX - Unix GCC/CC type compiler makefile(s) +WIN32 - Win32 Watcom compiler makefile +MSDOS - MS-DOS system type compiler makefile(s) + +This has been tested using the following compilers + +Watcom 10.5 Win32 and Extended DOS +Borland 3.1+ +DJGPP +GCC For HP-UX, SunOS 4.xx, Linux +CC for HP-UX, SunOS 4.xx diff --git a/install/unix/makefile b/install/unix/makefile old mode 100755 new mode 100644 diff --git a/install/win32/makefile.wat b/install/win32/makefile.wat new file mode 100644 index 0000000..cab2db2 --- /dev/null +++ b/install/win32/makefile.wat @@ -0,0 +1,152 @@ +# This is a makefile for watcom compatible make. +# This seems to work with Version 10.5 of Watcom C/C++ +# It produces DOS4GW executables and character mode Watcom NT executables + +# extension for object files +O = obj + +# commands +CC = wcc386 +LIB = wlib +ASM = as + +# name of temporary library script +TEMPFILE = $(TEMP)\temp.mak + +# Watcom Standard include directory, change to suit +STDINCDIR = \watcom\include + +# The places to look for include files (in order). +INCL = -i. -I$(RSAEURODIR) -I$(STDINCDIR) + +# Extra Defs + +# To select CPU type set CPUT to any of the following +# +# 386 = i386+ processor, 80386 and above processor +# 68k = M680x0 series processor. +# +# Leave empty to disable assembler routines. +# Not Used in Watcom Version. +# CPUT = 386 + +# Set to 1 for ANSI Standard Routine to be Used, only availible +# if assembler routines not it use. +# Dosn't seem to work with Watcom ?? +# ANSISTD = 1 + +# utility routines +del = del +COPY = copy + +# name of main executable to build +PROG = all + +# Standard DOS4GW Executable Flags. Change -3s to -4s for i486 +# CFLAGS = $(INCL) -3s -zq -ox -r -sg -zm -zdf -dPROTOTYPES=0 + +# Windows Win32 Executable Flags, works for 10.5 +CFLAGS = $(INCL) -4s -zq -ox -r -sg -dPROTOTYPES=0 + +ASMFL = $(INCL) -c -Wa,-L +MFLAGS = -I. -I$(RSAEURODIR) + +# The location of the common source directory. +RSAEURODIR = ..\source\ +RSAEUROLIB = rsaeuro.lib +RSAREFLIB = rsaref.lib + +# The location of the demo source directory. +DEMODIR = ..\demo\ + +all : demo $(RSAREFLIB) + +$(RSAREFLIB) : $(RSAEUROLIB) + $(COPY) $(RSAEUROLIB) $(RSAREFLIB) + +demo : redemo mdemo randemo + +randemo.exe : randemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 randemo.$(O) $(RSAEUROLIB) + del *.$(O) + +mdemo.exe : mdemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 mdemo.$(O) $(RSAEUROLIB) + del *.$(O) + +redemo.exe : redemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 redemo.$(O) $(RSAEUROLIB) + del *.$(O) + +$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O) rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O) r_stdlib.$(O) + $(LIB) -n $@ @rsa.wat + +randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)randemo.c + +mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)mdemo.c + +redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)redemo.c + +desc.$(O) : $(RSAEURODIR)desc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)des.h + $(CC) $(CFLAGS) $(RSAEURODIR)desc.c + echo -+$@ > rsa.wat + +shsc.$(O) : $(RSAEURODIR)shsc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)shs.h + $(CC) $(CFLAGS) $(RSAEURODIR)shsc.c + echo -+$@ >> rsa.wat + +md2c.$(O) : $(RSAEURODIR)md2c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md2.h + $(CC) $(CFLAGS) $(RSAEURODIR)md2c.c + echo -+$@ >> rsa.wat + +md4c.$(O) : $(RSAEURODIR)md4c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md4.h + $(CC) $(CFLAGS) $(RSAEURODIR)md4c.c + echo -+$@ >> rsa.wat + +md5c.$(O) : $(RSAEURODIR)md5c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)md5c.c + echo -+$@ >> rsa.wat + +nn.$(O) : $(RSAEURODIR)nn.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)nn.c + echo -+$@ >> rsa.wat + +prime.$(O) : $(RSAEURODIR)prime.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)prime.c + echo -+$@ >> rsa.wat + +rsa.$(O) : $(RSAEURODIR)rsa.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)rsa.c + echo -+$@ >> rsa.wat + +r_dh.$(O) : $(RSAEURODIR)r_dh.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_dh.c + echo -+$@ >> rsa.wat + +r_encode.$(O) : $(RSAEURODIR)r_encode.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_encode.c + echo -+$@ >> rsa.wat + +r_enhanc.$(O) : $(RSAEURODIR)r_enhanc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_enhanc.c + echo -+$@ >> rsa.wat + +r_keygen.$(O) : $(RSAEURODIR)r_keygen.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_keygen.c + echo -+$@ >> rsa.wat + +r_random.$(O) : $(RSAEURODIR)r_random.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_random.c + echo -+$@ >> rsa.wat + +r_stdlib.$(O) : $(RSAEURODIR)r_stdlib.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_stdlib.c + echo -+$@ >> rsa.wat + +# Dependencies for header files + +$(RSAREDIR)rsaeuro.h : $(RSAEURODIR)shs.h $(RSAEURODIR)nn.h $(RSAEURODIR)md2.h $(RSAEURODIR)md5.h $(RSAEURODIR)des.h $(RSAEURODIR)global.h + diff --git a/readme b/readme old mode 100755 new mode 100644 index 738198c..0d71c32 --- a/readme +++ b/readme @@ -1,18 +1,18 @@ -RSAEURO Version 1.02 Distribution - -In this distribution the various files are included in the directories -below. - -DOCS - RSAEURO Documentation Directory -DEMO - Demo Applications Directory -SOURCE - Source Code Directory -SCRIPTS - Demo Applications Script Files -INSTALL - Installation Instructions - -The documentation is supplied in both Postscript and ASCII formats. -(At the moment due a problem with Windows Word The main docs are only -availible as Postscript.) - -Please report any problems with the code or documentation to me on -the bug report form. Also any problems you may have in using the -toolkit. Please read the bug report form for more details. +RSAEURO Version 1.03 Distribution + +In this distribution the various files are included in the directories +below. + +DOCS - RSAEURO Documentation Directory +DEMO - Demo Applications Directory +SOURCE - Source Code Directory +SCRIPTS - Demo Applications Script Files +INSTALL - Installation Instructions + +The documentation is supplied in both Postscript and ASCII formats. +(At the moment due a problem with Windows Word The main docs are only +availible as Postscript.) + +Please report any problems with the code or documentation to me on +the bug report form. Also any problems you may have in using the +toolkit. Please read the bug report form for more details. diff --git a/scripts/1024-1.env b/scripts/1024-1.env old mode 100755 new mode 100644 diff --git a/scripts/1024-1.iv b/scripts/1024-1.iv old mode 100755 new mode 100644 diff --git a/scripts/1024-1.key b/scripts/1024-1.key old mode 100755 new mode 100644 diff --git a/scripts/1024-5.sig b/scripts/1024-5.sig old mode 100755 new mode 100644 diff --git a/scripts/1024.in b/scripts/1024.in old mode 100755 new mode 100644 diff --git a/scripts/1024.key b/scripts/1024.key old mode 100755 new mode 100644 diff --git a/scripts/508-1.env b/scripts/508-1.env old mode 100755 new mode 100644 diff --git a/scripts/508-1.iv b/scripts/508-1.iv old mode 100755 new mode 100644 diff --git a/scripts/508-1.key b/scripts/508-1.key old mode 100755 new mode 100644 diff --git a/scripts/508-5.sig b/scripts/508-5.sig old mode 100755 new mode 100644 diff --git a/scripts/508.in b/scripts/508.in old mode 100755 new mode 100644 diff --git a/scripts/508.key b/scripts/508.key old mode 100755 new mode 100644 diff --git a/scripts/512a.in b/scripts/512a.in old mode 100755 new mode 100644 diff --git a/scripts/512a1.env b/scripts/512a1.env old mode 100755 new mode 100644 diff --git a/scripts/512a1.iv b/scripts/512a1.iv old mode 100755 new mode 100644 diff --git a/scripts/512a1.key b/scripts/512a1.key old mode 100755 new mode 100644 diff --git a/scripts/512a1big.env b/scripts/512a1big.env old mode 100755 new mode 100644 diff --git a/scripts/512a1big.iv b/scripts/512a1big.iv old mode 100755 new mode 100644 diff --git a/scripts/512a1big.key b/scripts/512a1big.key old mode 100755 new mode 100644 diff --git a/scripts/512a2.env b/scripts/512a2.env old mode 100755 new mode 100644 diff --git a/scripts/512a2.iv b/scripts/512a2.iv old mode 100755 new mode 100644 diff --git a/scripts/512a2.key b/scripts/512a2.key old mode 100755 new mode 100644 diff --git a/scripts/512a2.sig b/scripts/512a2.sig old mode 100755 new mode 100644 diff --git a/scripts/512a3.env b/scripts/512a3.env old mode 100755 new mode 100644 diff --git a/scripts/512a3.iv b/scripts/512a3.iv old mode 100755 new mode 100644 diff --git a/scripts/512a3.key b/scripts/512a3.key old mode 100755 new mode 100644 diff --git a/scripts/512a5.sig b/scripts/512a5.sig old mode 100755 new mode 100644 diff --git a/scripts/512a5big.sig b/scripts/512a5big.sig old mode 100755 new mode 100644 diff --git a/scripts/512ax.env b/scripts/512ax.env old mode 100755 new mode 100644 diff --git a/scripts/512ax.iv b/scripts/512ax.iv old mode 100755 new mode 100644 diff --git a/scripts/512ax.key b/scripts/512ax.key old mode 100755 new mode 100644 diff --git a/scripts/767-1.env b/scripts/767-1.env old mode 100755 new mode 100644 diff --git a/scripts/767-1.iv b/scripts/767-1.iv old mode 100755 new mode 100644 diff --git a/scripts/767-1.key b/scripts/767-1.key old mode 100755 new mode 100644 diff --git a/scripts/767-5.sig b/scripts/767-5.sig old mode 100755 new mode 100644 diff --git a/scripts/767.in b/scripts/767.in old mode 100755 new mode 100644 diff --git a/scripts/767.key b/scripts/767.key old mode 100755 new mode 100644 diff --git a/scripts/bigfile b/scripts/bigfile old mode 100755 new mode 100644 index 3d4f37b..a655e67 --- a/scripts/bigfile +++ b/scripts/bigfile @@ -1,97 +1,97 @@ -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Done +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Done diff --git a/scripts/file b/scripts/file old mode 100755 new mode 100644 index d27e6b2..e20e856 --- a/scripts/file +++ b/scripts/file @@ -1 +1 @@ -Envelope opened. +Envelope opened. diff --git a/source/des.h b/source/des.h old mode 100755 new mode 100644 index 932c290..cda8056 --- a/source/des.h +++ b/source/des.h @@ -1,23 +1,21 @@ /* DES.H - header file for DESC.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid + same naming comventions that RSAREF uses. This should aid direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - DES Code header file. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _DES_H_ diff --git a/source/des386.s b/source/des386.s old mode 100755 new mode 100644 index fc31234..4607040 --- a/source/des386.s +++ b/source/des386.s @@ -1,7 +1,7 @@ /* DES386.S - Data Encryption Standard routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -26,8 +26,6 @@ 0.91 Current revision some minor bug fixes to original code. Comments revised to reflect original C code. - - 1.00 23/6/95, Final Release Version */ /* Crafty DES Function */ diff --git a/source/desc.c b/source/desc.c old mode 100755 new mode 100644 index 99368fd..79bfda4 --- a/source/desc.c +++ b/source/desc.c @@ -1,797 +1,797 @@ -/* - DESC.C - Data Encryption Standard routines for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - Based on Outerbridge's D3DES (V5.09) 1992 Vintage. - - DESX(tm) - RSA Data Security. - - DES386 to be define ONLY in conjunction with 386 compiled - code. - - All Trademarks Acknowledged. - - Revision history - 0.90 First revision, this was the original retrofitted D3DES - version. - - 0.91 Second revision, retrofitted new S-box array and new desfunc - routine. Marginally quicker code improves DES throughput. - - 0.92 Current revision, added support for 386 assembler desfunc - routine, with altered S boxes and key generation to support easier - S box look up. Code that uses 386 desfunc is about 80K per sec - faster than RSAREF(tm) code. -*/ - -#include "rsaeuro.h" -#include "des.h" - -static UINT2 bytebit[8] = { - 0200, 0100, 040, 020, 010, 04, 02, 01 -}; - -static UINT4 bigbyte[24] = { - 0x800000L, 0x400000L, 0x200000L, 0x100000L, - 0x80000L, 0x40000L, 0x20000L, 0x10000L, - 0x8000L, 0x4000L, 0x2000L, 0x1000L, - 0x800L, 0x400L, 0x200L, 0x100L, - 0x80L, 0x40L, 0x20L, 0x10L, - 0x8L, 0x4L, 0x2L, 0x1L -}; - -static unsigned char totrot[16] = { - 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 -}; - -static unsigned char pc1[56] = { - 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, - 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, - 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, - 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 -}; - -static unsigned char pc2[48] = { - 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, - 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, - 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, - 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 -}; - -#ifndef DES386 - -UINT4 Spbox[8][64] = { - 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, - 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, - 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, - 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, - 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, - 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, - 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, - 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, - 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, - 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, - 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, - 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, - 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, - 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, - 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, - 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L, - 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, - 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, - 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, - 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, - 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, - 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, - 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, - 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, - 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, - 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, - 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, - 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, - 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, - 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, - 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, - 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L, - 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, - 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, - 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, - 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, - 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, - 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, - 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, - 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, - 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, - 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, - 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, - 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, - 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, - 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, - 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, - 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L, - 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, - 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, - 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, - 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, - 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, - 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, - 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, - 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, - 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, - 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, - 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, - 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, - 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, - 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, - 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, - 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L, - 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, - 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, - 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, - 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, - 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, - 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, - 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, - 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, - 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, - 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, - 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, - 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, - 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, - 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, - 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, - 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L, - 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, - 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, - 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, - 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, - 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, - 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, - 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, - 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, - 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, - 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, - 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, - 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, - 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, - 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, - 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, - 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L, - 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, - 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, - 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, - 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, - 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, - 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, - 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, - 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, - 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, - 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, - 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, - 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, - 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, - 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, - 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, - 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L, - 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, - 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, - 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, - 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, - 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, - 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, - 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, - 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, - 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, - 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, - 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, - 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, - 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, - 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, - 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, - 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L -}; - -#else - /* S box tables for assembler desfunc */ - -unsigned long Spbox[8][64] = { - 0x04041000,0x00000000,0x00040000,0x04041010, - 0x04040010,0x00041010,0x00000010,0x00040000, - 0x00001000,0x04041000,0x04041010,0x00001000, - 0x04001010,0x04040010,0x04000000,0x00000010, - 0x00001010,0x04001000,0x04001000,0x00041000, - 0x00041000,0x04040000,0x04040000,0x04001010, - 0x00040010,0x04000010,0x04000010,0x00040010, - 0x00000000,0x00001010,0x00041010,0x04000000, - 0x00040000,0x04041010,0x00000010,0x04040000, - 0x04041000,0x04000000,0x04000000,0x00001000, - 0x04040010,0x00040000,0x00041000,0x04000010, - 0x00001000,0x00000010,0x04001010,0x00041010, - 0x04041010,0x00040010,0x04040000,0x04001010, - 0x04000010,0x00001010,0x00041010,0x04041000, - 0x00001010,0x04001000,0x04001000,0x00000000, - 0x00040010,0x00041000,0x00000000,0x04040010, - 0x00420082,0x00020002,0x00020000,0x00420080, - 0x00400000,0x00000080,0x00400082,0x00020082, - 0x00000082,0x00420082,0x00420002,0x00000002, - 0x00020002,0x00400000,0x00000080,0x00400082, - 0x00420000,0x00400080,0x00020082,0x00000000, - 0x00000002,0x00020000,0x00420080,0x00400002, - 0x00400080,0x00000082,0x00000000,0x00420000, - 0x00020080,0x00420002,0x00400002,0x00020080, - 0x00000000,0x00420080,0x00400082,0x00400000, - 0x00020082,0x00400002,0x00420002,0x00020000, - 0x00400002,0x00020002,0x00000080,0x00420082, - 0x00420080,0x00000080,0x00020000,0x00000002, - 0x00020080,0x00420002,0x00400000,0x00000082, - 0x00400080,0x00020082,0x00000082,0x00400080, - 0x00420000,0x00000000,0x00020002,0x00020080, - 0x00000002,0x00400082,0x00420082,0x00420000, - 0x00000820,0x20080800,0x00000000,0x20080020, - 0x20000800,0x00000000,0x00080820,0x20000800, - 0x00080020,0x20000020,0x20000020,0x00080000, - 0x20080820,0x00080020,0x20080000,0x00000820, - 0x20000000,0x00000020,0x20080800,0x00000800, - 0x00080800,0x20080000,0x20080020,0x00080820, - 0x20000820,0x00080800,0x00080000,0x20000820, - 0x00000020,0x20080820,0x00000800,0x20000000, - 0x20080800,0x20000000,0x00080020,0x00000820, - 0x00080000,0x20080800,0x20000800,0x00000000, - 0x00000800,0x00080020,0x20080820,0x20000800, - 0x20000020,0x00000800,0x00000000,0x20080020, - 0x20000820,0x00080000,0x20000000,0x20080820, - 0x00000020,0x00080820,0x00080800,0x20000020, - 0x20080000,0x20000820,0x00000820,0x20080000, - 0x00080820,0x00000020,0x20080020,0x00080800, - 0x02008004,0x00008204,0x00008204,0x00000200, - 0x02008200,0x02000204,0x02000004,0x00008004, - 0x00000000,0x02008000,0x02008000,0x02008204, - 0x00000204,0x00000000,0x02000200,0x02000004, - 0x00000004,0x00008000,0x02000000,0x02008004, - 0x00000200,0x02000000,0x00008004,0x00008200, - 0x02000204,0x00000004,0x00008200,0x02000200, - 0x00008000,0x02008200,0x02008204,0x00000204, - 0x02000200,0x02000004,0x02008000,0x02008204, - 0x00000204,0x00000000,0x00000000,0x02008000, - 0x00008200,0x02000200,0x02000204,0x00000004, - 0x02008004,0x00008204,0x00008204,0x00000200, - 0x02008204,0x00000204,0x00000004,0x00008000, - 0x02000004,0x00008004,0x02008200,0x02000204, - 0x00008004,0x00008200,0x02000000,0x02008004, - 0x00000200,0x02000000,0x00008000,0x02008200, - 0x00000400,0x08200400,0x08200000,0x08000401, - 0x00200000,0x00000400,0x00000001,0x08200000, - 0x00200401,0x00200000,0x08000400,0x00200401, - 0x08000401,0x08200001,0x00200400,0x00000001, - 0x08000000,0x00200001,0x00200001,0x00000000, - 0x00000401,0x08200401,0x08200401,0x08000400, - 0x08200001,0x00000401,0x00000000,0x08000001, - 0x08200400,0x08000000,0x08000001,0x00200400, - 0x00200000,0x08000401,0x00000400,0x08000000, - 0x00000001,0x08200000,0x08000401,0x00200401, - 0x08000400,0x00000001,0x08200001,0x08200400, - 0x00200401,0x00000400,0x08000000,0x08200001, - 0x08200401,0x00200400,0x08000001,0x08200401, - 0x08200000,0x00000000,0x00200001,0x08000001, - 0x00200400,0x08000400,0x00000401,0x00200000, - 0x00000000,0x00200001,0x08200400,0x00000401, - 0x80000040,0x81000000,0x00010000,0x81010040, - 0x81000000,0x00000040,0x81010040,0x01000000, - 0x80010000,0x01010040,0x01000000,0x80000040, - 0x01000040,0x80010000,0x80000000,0x00010040, - 0x00000000,0x01000040,0x80010040,0x00010000, - 0x01010000,0x80010040,0x00000040,0x81000040, - 0x81000040,0x00000000,0x01010040,0x81010000, - 0x00010040,0x01010000,0x81010000,0x80000000, - 0x80010000,0x00000040,0x81000040,0x01010000, - 0x81010040,0x01000000,0x00010040,0x80000040, - 0x01000000,0x80010000,0x80000000,0x00010040, - 0x80000040,0x81010040,0x01010000,0x81000000, - 0x01010040,0x81010000,0x00000000,0x81000040, - 0x00000040,0x00010000,0x81000000,0x01010040, - 0x00010000,0x01000040,0x80010040,0x00000000, - 0x81010000,0x80000000,0x01000040,0x80010040, - 0x00800000,0x10800008,0x10002008,0x00000000, - 0x00002000,0x10002008,0x00802008,0x10802000, - 0x10802008,0x00800000,0x00000000,0x10000008, - 0x00000008,0x10000000,0x10800008,0x00002008, - 0x10002000,0x00802008,0x00800008,0x10002000, - 0x10000008,0x10800000,0x10802000,0x00800008, - 0x10800000,0x00002000,0x00002008,0x10802008, - 0x00802000,0x00000008,0x10000000,0x00802000, - 0x10000000,0x00802000,0x00800000,0x10002008, - 0x10002008,0x10800008,0x10800008,0x00000008, - 0x00800008,0x10000000,0x10002000,0x00800000, - 0x10802000,0x00002008,0x00802008,0x10802000, - 0x00002008,0x10000008,0x10802008,0x10800000, - 0x00802000,0x00000000,0x00000008,0x10802008, - 0x00000000,0x00802008,0x10800000,0x00002000, - 0x10000008,0x10002000,0x00002000,0x00800008, - 0x40004100,0x00004000,0x00100000,0x40104100, - 0x40000000,0x40004100,0x00000100,0x40000000, - 0x00100100,0x40100000,0x40104100,0x00104000, - 0x40104000,0x00104100,0x00004000,0x00000100, - 0x40100000,0x40000100,0x40004000,0x00004100, - 0x00104000,0x00100100,0x40100100,0x40104000, - 0x00004100,0x00000000,0x00000000,0x40100100, - 0x40000100,0x40004000,0x00104100,0x00100000, - 0x00104100,0x00100000,0x40104000,0x00004000, - 0x00000100,0x40100100,0x00004000,0x00104100, - 0x40004000,0x00000100,0x40000100,0x40100000, - 0x40100100,0x40000000,0x00100000,0x40004100, - 0x00000000,0x40104100,0x00100100,0x40000100, - 0x40100000,0x40004000,0x40004100,0x00000000, - 0x40104100,0x00104000,0x00104000,0x00004100, - 0x00004100,0x00100100,0x40000000,0x40104000, -}; - -#endif - -void unscrunch PROTO_LIST ((unsigned char *, UINT4 *)); -void scrunch PROTO_LIST ((UINT4 *, unsigned char *)); -void deskey PROTO_LIST ((UINT4 *, unsigned char *, int)); -static void cookey PROTO_LIST ((UINT4 *, UINT4 *, int)); -void desfunc PROTO_LIST ((UINT4 *, UINT4 *)); - -/* Initialize context. Caller must zeroize the context when finished. */ - -void DES_CBCInit(context, key, iv, encrypt) -DES_CBC_CTX *context; /* context */ -unsigned char *key; /* key */ -unsigned char *iv; /* initializing vector */ -int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ -{ - /* Save encrypt flag to context. */ - context->encrypt = encrypt; - - /* Pack initializing vector into context. */ - - scrunch(context->iv, iv); - scrunch(context->originalIV, iv); - - /* Precompute key schedule */ - - deskey(context->subkeys, key, encrypt); -} - -/* DES-CBC block update operation. Continues a DES-CBC encryption - operation, processing eight-byte message blocks, and updating - the context. - - This requires len to be a multiple of 8. -*/ -int DES_CBCUpdate(context, output, input, len) -DES_CBC_CTX *context; /* context */ -unsigned char *output; /* output block */ -unsigned char *input; /* input block */ -unsigned int len; /* length of input and output blocks */ -{ - UINT4 inputBlock[2], work[2]; - unsigned int i; - - if(len % 8) /* block size check */ - return(RE_LEN); - - for(i = 0; i < len/8; i++) { - scrunch(inputBlock, &input[8*i]); - - /* Chain if encrypting. */ - - if(context->encrypt == 0) { - *work = *inputBlock; - *(work+1) = *(inputBlock+1); - }else{ - *work = *inputBlock ^ *context->iv; - *(work+1) = *(inputBlock+1) ^ *(context->iv+1); - } - - desfunc(work, context->subkeys); - - /* Chain if decrypting, then update IV. */ - - if(context->encrypt == 0) { - *work ^= *context->iv; - *(work+1) ^= *(context->iv+1); - *context->iv = *inputBlock; - *(context->iv+1) = *(inputBlock+1); - }else{ - *context->iv = *work; - *(context->iv+1) = *(work+1); - } - unscrunch (&output[8*i], work); - } - - /* Clear sensitive information. */ - - R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); - R_memset((POINTER)work, 0, sizeof(work)); - - return(IDOK); -} - -void DES_CBCRestart(context) -DES_CBC_CTX *context; /* context */ -{ - /* Restore the original IV */ - - *context->iv = *context->originalIV; - *(context->iv+1) = *(context->originalIV+1); -} - -/* Initialize context. Caller should clear the context when finished. - The key has the DES key, input whitener and output whitener concatenated. - This is the RSADSI special DES implementation. -*/ -void DESX_CBCInit(context, key, iv, encrypt) -DESX_CBC_CTX *context; /* context */ -unsigned char *key; /* DES key and whiteners */ -unsigned char *iv; /* DES initializing vector */ -int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ -{ - /* Save encrypt flag to context. */ - - context->encrypt = encrypt; - - /* Pack initializing vector and whiteners into context. */ - - scrunch(context->iv, iv); - scrunch(context->inputWhitener, key + 8); - scrunch(context->outputWhitener, key + 16); - /* Save the IV for use in Restart */ - scrunch(context->originalIV, iv); - - /* Precompute key schedule. */ - - deskey (context->subkeys, key, encrypt); -} - -/* DESX-CBC block update operation. Continues a DESX-CBC encryption - operation, processing eight-byte message blocks, and updating - the context. This is the RSADSI special DES implementation. - - Requires len to a multiple of 8. -*/ - -int DESX_CBCUpdate (context, output, input, len) -DESX_CBC_CTX *context; /* context */ -unsigned char *output; /* output block */ -unsigned char *input; /* input block */ -unsigned int len; /* length of input and output blocks */ -{ - UINT4 inputBlock[2], work[2]; - unsigned int i; - - if(len % 8) /* Length check */ - return(RE_LEN); - - for(i = 0; i < len/8; i++) { - scrunch(inputBlock, &input[8*i]); - - /* Chain if encrypting, and xor with whitener. */ - - if(context->encrypt == 0) { - *work = *inputBlock ^ *context->outputWhitener; - *(work+1) = *(inputBlock+1) ^ *(context->outputWhitener+1); - }else{ - *work = *inputBlock ^ *context->iv ^ *context->inputWhitener; - *(work+1) = *(inputBlock+1) ^ *(context->iv+1) ^ *(context->inputWhitener+1); - } - - desfunc(work, context->subkeys); - - /* Xor with whitener, chain if decrypting, then update IV. */ - - if(context->encrypt == 0) { - *work ^= *context->iv ^ *context->inputWhitener; - *(work+1) ^= *(context->iv+1) ^ *(context->inputWhitener+1); - *(context->iv) = *inputBlock; - *(context->iv+1) = *(inputBlock+1); - }else{ - *work ^= *context->outputWhitener; - *(work+1) ^= *(context->outputWhitener+1); - *context->iv = *work; - *(context->iv+1) = *(work+1); - } - unscrunch(&output[8*i], work); - } - - R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); - R_memset((POINTER)work, 0, sizeof(work)); - - return(IDOK); -} - -void DESX_CBCRestart(context) -DESX_CBC_CTX *context; /* context */ -{ - /* Restore the original IV */ - *context->iv = *context->originalIV; - *(context->iv+1) = *(context->originalIV+1); -} - -/* Initialize context. Caller must zeroize the context when finished. */ - -void DES3_CBCInit(context, key, iv, encrypt) -DES3_CBC_CTX *context; /* context */ -unsigned char *key; /* key */ -unsigned char *iv; /* initializing vector */ -int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ -{ - /* Copy encrypt flag to context. */ - context->encrypt = encrypt; - - /* Pack initializing vector into context. */ - - scrunch(context->iv, iv); - - /* Save the IV for use in Restart */ - scrunch(context->originalIV, iv); - - /* Precompute key schedules. */ - - deskey(context->subkeys[0], encrypt ? key : &key[16], encrypt); - deskey(context->subkeys[1], &key[8], !encrypt); - deskey(context->subkeys[2], encrypt ? &key[16] : key, encrypt); -} - -int DES3_CBCUpdate(context, output, input, len) -DES3_CBC_CTX *context; /* context */ -unsigned char *output; /* output block */ -unsigned char *input; /* input block */ -unsigned int len; /* length of input and output blocks */ -{ - UINT4 inputBlock[2], work[2]; - unsigned int i; - - if(len % 8) /* length check */ - return(RE_LEN); - - for(i = 0; i < len/8; i++) { - scrunch(inputBlock, &input[8*i]); - - /* Chain if encrypting. */ - - if(context->encrypt == 0) { - *work = *inputBlock; - *(work+1) = *(inputBlock+1); - } - else { - *work = *inputBlock ^ *context->iv; - *(work+1) = *(inputBlock+1) ^ *(context->iv+1); - } - - desfunc(work, context->subkeys[0]); - desfunc(work, context->subkeys[1]); - desfunc(work, context->subkeys[2]); - - /* Chain if decrypting, then update IV. */ - - if(context->encrypt == 0) { - *work ^= *context->iv; - *(work+1) ^= *(context->iv+1); - *context->iv = *inputBlock; - *(context->iv+1) = *(inputBlock+1); - } - else { - *context->iv = *work; - *(context->iv+1) = *(work+1); - } - unscrunch(&output[8*i], work); - } - - R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); - R_memset((POINTER)work, 0, sizeof(work)); - - return (0); -} - -void DES3_CBCRestart (context) -DES3_CBC_CTX *context; /* context */ -{ - /* Restore the original IV */ - *context->iv = *context->originalIV; - *(context->iv+1) = *(context->originalIV+1); -} - -void scrunch (into, outof) -UINT4 *into; -unsigned char *outof; -{ - *into = (*outof++ & 0xffL) << 24; - *into |= (*outof++ & 0xffL) << 16; - *into |= (*outof++ & 0xffL) << 8; - *into++ |= (*outof++ & 0xffL); - *into = (*outof++ & 0xffL) << 24; - *into |= (*outof++ & 0xffL) << 16; - *into |= (*outof++ & 0xffL) << 8; - *into |= (*outof & 0xffL); -} - -void unscrunch(into, outof) -unsigned char *into; -UINT4 *outof; -{ - *into++ = (unsigned char)((*outof >> 24) & 0xffL); - *into++ = (unsigned char)((*outof >> 16) & 0xffL); - *into++ = (unsigned char)((*outof >> 8) & 0xffL); - *into++ = (unsigned char)( *outof++ & 0xffL); - *into++ = (unsigned char)((*outof >> 24) & 0xffL); - *into++ = (unsigned char)((*outof >> 16) & 0xffL); - *into++ = (unsigned char)((*outof >> 8) & 0xffL); - *into = (unsigned char)( *outof & 0xffL); -} - -/* Compute DES Subkeys */ - -void deskey(subkeys, key, encrypt) -UINT4 subkeys[32]; -unsigned char key[8]; -int encrypt; -{ - UINT4 kn[32]; - int i, j, l, m, n; - unsigned char pc1m[56], pcr[56]; - - for(j = 0; j < 56; j++) { - l = pc1[j]; - m = l & 07; - pc1m[j] = (unsigned char)((key[l >> 3] & bytebit[m]) ? 1 : 0); - } - for(i = 0; i < 16; i++) { - m = i << 1; - n = m + 1; - kn[m] = kn[n] = 0L; - for(j = 0; j < 28; j++) { - l = j + totrot[i]; - if(l < 28) pcr[j] = pc1m[l]; - else pcr[j] = pc1m[l - 28]; - } - for(j = 28; j < 56; j++) { - l = j + totrot[i]; - if(l < 56) pcr[j] = pc1m[l]; - else pcr[j] = pc1m[l - 28]; - } - for(j = 0; j < 24; j++) { - if(pcr[pc2[j]]) - kn[m] |= bigbyte[j]; - if(pcr[pc2[j+24]]) - kn[n] |= bigbyte[j]; - } - } - cookey(subkeys, kn, encrypt); - -#ifdef DES386 - for(i=0;i < 32;i++) - subkeys[i] <<= 2; -#endif - - R_memset((POINTER)pc1m, 0, sizeof(pc1m)); - R_memset((POINTER)pcr, 0, sizeof(pcr)); - R_memset((POINTER)kn, 0, sizeof(kn)); -} - -static void cookey(subkeys, kn, encrypt) -UINT4 *subkeys; -UINT4 *kn; -int encrypt; -{ - UINT4 *cooked, *raw0, *raw1; - int increment; - unsigned int i; - - raw1 = kn; - cooked = encrypt ? subkeys : &subkeys[30]; - increment = encrypt ? 1 : -3; - - for (i = 0; i < 16; i++, raw1++) { - raw0 = raw1++; - *cooked = (*raw0 & 0x00fc0000L) << 6; - *cooked |= (*raw0 & 0x00000fc0L) << 10; - *cooked |= (*raw1 & 0x00fc0000L) >> 10; - *cooked++ |= (*raw1 & 0x00000fc0L) >> 6; - *cooked = (*raw0 & 0x0003f000L) << 12; - *cooked |= (*raw0 & 0x0000003fL) << 16; - *cooked |= (*raw1 & 0x0003f000L) >> 4; - *cooked |= (*raw1 & 0x0000003fL); - cooked += increment; - } -} - -#ifndef DES386 /* ignore C version in favor of 386 ONLY desfunc */ - -#define F(l,r,key){\ - work = ((r >> 4) | (r << 28)) ^ *key;\ - l ^= Spbox[6][work & 0x3f];\ - l ^= Spbox[4][(work >> 8) & 0x3f];\ - l ^= Spbox[2][(work >> 16) & 0x3f];\ - l ^= Spbox[0][(work >> 24) & 0x3f];\ - work = r ^ *(key+1);\ - l ^= Spbox[7][work & 0x3f];\ - l ^= Spbox[5][(work >> 8) & 0x3f];\ - l ^= Spbox[3][(work >> 16) & 0x3f];\ - l ^= Spbox[1][(work >> 24) & 0x3f];\ -} - -/* This desfunc code is marginally quicker than that uses in - RSAREF(tm) -*/ - -void desfunc(block,ks) -UINT4 *block; /* Data block */ -UINT4 *ks; /* Key schedule */ -{ - unsigned long left,right,work; - - left = block[0]; - right = block[1]; - - work = ((left >> 4) ^ right) & 0x0f0f0f0f; - right ^= work; - left ^= work << 4; - work = ((left >> 16) ^ right) & 0xffff; - right ^= work; - left ^= work << 16; - work = ((right >> 2) ^ left) & 0x33333333; - left ^= work; - right ^= (work << 2); - work = ((right >> 8) ^ left) & 0xff00ff; - left ^= work; - right ^= (work << 8); - right = (right << 1) | (right >> 31); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left << 1) | (left >> 31); - - /* Now do the 16 rounds */ - F(left,right,&ks[0]); - F(right,left,&ks[2]); - F(left,right,&ks[4]); - F(right,left,&ks[6]); - F(left,right,&ks[8]); - F(right,left,&ks[10]); - F(left,right,&ks[12]); - F(right,left,&ks[14]); - F(left,right,&ks[16]); - F(right,left,&ks[18]); - F(left,right,&ks[20]); - F(right,left,&ks[22]); - F(left,right,&ks[24]); - F(right,left,&ks[26]); - F(left,right,&ks[28]); - F(right,left,&ks[30]); - - right = (right << 31) | (right >> 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left >> 1) | (left << 31); - work = ((left >> 8) ^ right) & 0xff00ff; - right ^= work; - left ^= work << 8; - work = ((left >> 2) ^ right) & 0x33333333; - right ^= work; - left ^= work << 2; - work = ((right >> 16) ^ left) & 0xffff; - left ^= work; - right ^= work << 16; - work = ((right >> 4) ^ left) & 0x0f0f0f0f; - left ^= work; - right ^= work << 4; - - *block++ = right; - *block = left; -} - -#endif /* DES386 endif */ +/* + DESC.C - Data Encryption Standard routines for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + Based on Outerbridge's D3DES (V5.09) 1992 Vintage. + + DESX(tm) - RSA Data Security. + + DES386 to be define ONLY in conjunction with 386 compiled + code. + + All Trademarks Acknowledged. + + Revision history + 0.90 First revision, this was the original retrofitted D3DES + version. + + 0.91 Second revision, retrofitted new S-box array and new desfunc + routine. Marginally quicker code improves DES throughput. + + 0.92 Current revision, added support for 386 assembler desfunc + routine, with altered S boxes and key generation to support easier + S box look up. Code that uses 386 desfunc is about 80K per sec + faster than RSAREF(tm) code. +*/ + +#include "rsaeuro.h" +#include "des.h" + +static UINT2 bytebit[8] = { + 0200, 0100, 040, 020, 010, 04, 02, 01 +}; + +static UINT4 bigbyte[24] = { + 0x800000L, 0x400000L, 0x200000L, 0x100000L, + 0x80000L, 0x40000L, 0x20000L, 0x10000L, + 0x8000L, 0x4000L, 0x2000L, 0x1000L, + 0x800L, 0x400L, 0x200L, 0x100L, + 0x80L, 0x40L, 0x20L, 0x10L, + 0x8L, 0x4L, 0x2L, 0x1L +}; + +static unsigned char totrot[16] = { + 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 +}; + +static unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 +}; + +static unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 +}; + +#ifndef DES386 + +UINT4 Spbox[8][64] = { + 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, + 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, + 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, + 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, + 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, + 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, + 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, + 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, + 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, + 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, + 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, + 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, + 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, + 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L, + 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, + 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, + 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, + 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, + 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, + 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, + 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, + 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, + 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, + 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, + 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, + 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, + 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, + 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, + 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, + 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L, + 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, + 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, + 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, + 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, + 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, + 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, + 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, + 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, + 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, + 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, + 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, + 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, + 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, + 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, + 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, + 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, + 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, + 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, + 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, + 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, + 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, + 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, + 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, + 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L, + 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, + 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, + 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, + 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, + 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, + 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, + 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, + 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, + 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, + 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, + 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, + 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, + 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, + 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, + 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, + 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L, + 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, + 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, + 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, + 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, + 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, + 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, + 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, + 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, + 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, + 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, + 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, + 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, + 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, + 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L, + 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, + 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, + 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, + 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, + 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, + 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, + 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, + 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, + 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, + 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, + 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, + 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, + 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, + 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, + 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, + 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L, + 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, + 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, + 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, + 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, + 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, + 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, + 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, + 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, + 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, + 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, + 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, + 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, + 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, + 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, + 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, + 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L +}; + +#else + /* S box tables for assembler desfunc */ + +unsigned long Spbox[8][64] = { + 0x04041000,0x00000000,0x00040000,0x04041010, + 0x04040010,0x00041010,0x00000010,0x00040000, + 0x00001000,0x04041000,0x04041010,0x00001000, + 0x04001010,0x04040010,0x04000000,0x00000010, + 0x00001010,0x04001000,0x04001000,0x00041000, + 0x00041000,0x04040000,0x04040000,0x04001010, + 0x00040010,0x04000010,0x04000010,0x00040010, + 0x00000000,0x00001010,0x00041010,0x04000000, + 0x00040000,0x04041010,0x00000010,0x04040000, + 0x04041000,0x04000000,0x04000000,0x00001000, + 0x04040010,0x00040000,0x00041000,0x04000010, + 0x00001000,0x00000010,0x04001010,0x00041010, + 0x04041010,0x00040010,0x04040000,0x04001010, + 0x04000010,0x00001010,0x00041010,0x04041000, + 0x00001010,0x04001000,0x04001000,0x00000000, + 0x00040010,0x00041000,0x00000000,0x04040010, + 0x00420082,0x00020002,0x00020000,0x00420080, + 0x00400000,0x00000080,0x00400082,0x00020082, + 0x00000082,0x00420082,0x00420002,0x00000002, + 0x00020002,0x00400000,0x00000080,0x00400082, + 0x00420000,0x00400080,0x00020082,0x00000000, + 0x00000002,0x00020000,0x00420080,0x00400002, + 0x00400080,0x00000082,0x00000000,0x00420000, + 0x00020080,0x00420002,0x00400002,0x00020080, + 0x00000000,0x00420080,0x00400082,0x00400000, + 0x00020082,0x00400002,0x00420002,0x00020000, + 0x00400002,0x00020002,0x00000080,0x00420082, + 0x00420080,0x00000080,0x00020000,0x00000002, + 0x00020080,0x00420002,0x00400000,0x00000082, + 0x00400080,0x00020082,0x00000082,0x00400080, + 0x00420000,0x00000000,0x00020002,0x00020080, + 0x00000002,0x00400082,0x00420082,0x00420000, + 0x00000820,0x20080800,0x00000000,0x20080020, + 0x20000800,0x00000000,0x00080820,0x20000800, + 0x00080020,0x20000020,0x20000020,0x00080000, + 0x20080820,0x00080020,0x20080000,0x00000820, + 0x20000000,0x00000020,0x20080800,0x00000800, + 0x00080800,0x20080000,0x20080020,0x00080820, + 0x20000820,0x00080800,0x00080000,0x20000820, + 0x00000020,0x20080820,0x00000800,0x20000000, + 0x20080800,0x20000000,0x00080020,0x00000820, + 0x00080000,0x20080800,0x20000800,0x00000000, + 0x00000800,0x00080020,0x20080820,0x20000800, + 0x20000020,0x00000800,0x00000000,0x20080020, + 0x20000820,0x00080000,0x20000000,0x20080820, + 0x00000020,0x00080820,0x00080800,0x20000020, + 0x20080000,0x20000820,0x00000820,0x20080000, + 0x00080820,0x00000020,0x20080020,0x00080800, + 0x02008004,0x00008204,0x00008204,0x00000200, + 0x02008200,0x02000204,0x02000004,0x00008004, + 0x00000000,0x02008000,0x02008000,0x02008204, + 0x00000204,0x00000000,0x02000200,0x02000004, + 0x00000004,0x00008000,0x02000000,0x02008004, + 0x00000200,0x02000000,0x00008004,0x00008200, + 0x02000204,0x00000004,0x00008200,0x02000200, + 0x00008000,0x02008200,0x02008204,0x00000204, + 0x02000200,0x02000004,0x02008000,0x02008204, + 0x00000204,0x00000000,0x00000000,0x02008000, + 0x00008200,0x02000200,0x02000204,0x00000004, + 0x02008004,0x00008204,0x00008204,0x00000200, + 0x02008204,0x00000204,0x00000004,0x00008000, + 0x02000004,0x00008004,0x02008200,0x02000204, + 0x00008004,0x00008200,0x02000000,0x02008004, + 0x00000200,0x02000000,0x00008000,0x02008200, + 0x00000400,0x08200400,0x08200000,0x08000401, + 0x00200000,0x00000400,0x00000001,0x08200000, + 0x00200401,0x00200000,0x08000400,0x00200401, + 0x08000401,0x08200001,0x00200400,0x00000001, + 0x08000000,0x00200001,0x00200001,0x00000000, + 0x00000401,0x08200401,0x08200401,0x08000400, + 0x08200001,0x00000401,0x00000000,0x08000001, + 0x08200400,0x08000000,0x08000001,0x00200400, + 0x00200000,0x08000401,0x00000400,0x08000000, + 0x00000001,0x08200000,0x08000401,0x00200401, + 0x08000400,0x00000001,0x08200001,0x08200400, + 0x00200401,0x00000400,0x08000000,0x08200001, + 0x08200401,0x00200400,0x08000001,0x08200401, + 0x08200000,0x00000000,0x00200001,0x08000001, + 0x00200400,0x08000400,0x00000401,0x00200000, + 0x00000000,0x00200001,0x08200400,0x00000401, + 0x80000040,0x81000000,0x00010000,0x81010040, + 0x81000000,0x00000040,0x81010040,0x01000000, + 0x80010000,0x01010040,0x01000000,0x80000040, + 0x01000040,0x80010000,0x80000000,0x00010040, + 0x00000000,0x01000040,0x80010040,0x00010000, + 0x01010000,0x80010040,0x00000040,0x81000040, + 0x81000040,0x00000000,0x01010040,0x81010000, + 0x00010040,0x01010000,0x81010000,0x80000000, + 0x80010000,0x00000040,0x81000040,0x01010000, + 0x81010040,0x01000000,0x00010040,0x80000040, + 0x01000000,0x80010000,0x80000000,0x00010040, + 0x80000040,0x81010040,0x01010000,0x81000000, + 0x01010040,0x81010000,0x00000000,0x81000040, + 0x00000040,0x00010000,0x81000000,0x01010040, + 0x00010000,0x01000040,0x80010040,0x00000000, + 0x81010000,0x80000000,0x01000040,0x80010040, + 0x00800000,0x10800008,0x10002008,0x00000000, + 0x00002000,0x10002008,0x00802008,0x10802000, + 0x10802008,0x00800000,0x00000000,0x10000008, + 0x00000008,0x10000000,0x10800008,0x00002008, + 0x10002000,0x00802008,0x00800008,0x10002000, + 0x10000008,0x10800000,0x10802000,0x00800008, + 0x10800000,0x00002000,0x00002008,0x10802008, + 0x00802000,0x00000008,0x10000000,0x00802000, + 0x10000000,0x00802000,0x00800000,0x10002008, + 0x10002008,0x10800008,0x10800008,0x00000008, + 0x00800008,0x10000000,0x10002000,0x00800000, + 0x10802000,0x00002008,0x00802008,0x10802000, + 0x00002008,0x10000008,0x10802008,0x10800000, + 0x00802000,0x00000000,0x00000008,0x10802008, + 0x00000000,0x00802008,0x10800000,0x00002000, + 0x10000008,0x10002000,0x00002000,0x00800008, + 0x40004100,0x00004000,0x00100000,0x40104100, + 0x40000000,0x40004100,0x00000100,0x40000000, + 0x00100100,0x40100000,0x40104100,0x00104000, + 0x40104000,0x00104100,0x00004000,0x00000100, + 0x40100000,0x40000100,0x40004000,0x00004100, + 0x00104000,0x00100100,0x40100100,0x40104000, + 0x00004100,0x00000000,0x00000000,0x40100100, + 0x40000100,0x40004000,0x00104100,0x00100000, + 0x00104100,0x00100000,0x40104000,0x00004000, + 0x00000100,0x40100100,0x00004000,0x00104100, + 0x40004000,0x00000100,0x40000100,0x40100000, + 0x40100100,0x40000000,0x00100000,0x40004100, + 0x00000000,0x40104100,0x00100100,0x40000100, + 0x40100000,0x40004000,0x40004100,0x00000000, + 0x40104100,0x00104000,0x00104000,0x00004100, + 0x00004100,0x00100100,0x40000000,0x40104000, +}; + +#endif + +void unscrunch PROTO_LIST ((unsigned char *, UINT4 *)); +void scrunch PROTO_LIST ((UINT4 *, unsigned char *)); +void deskey PROTO_LIST ((UINT4 *, unsigned char *, int)); +static void cookey PROTO_LIST ((UINT4 *, UINT4 *, int)); +void desfunc PROTO_LIST ((UINT4 *, UINT4 *)); + +/* Initialize context. Caller must zeroize the context when finished. */ + +void DES_CBCInit(context, key, iv, encrypt) +DES_CBC_CTX *context; /* context */ +unsigned char *key; /* key */ +unsigned char *iv; /* initializing vector */ +int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ +{ + /* Save encrypt flag to context. */ + context->encrypt = encrypt; + + /* Pack initializing vector into context. */ + + scrunch(context->iv, iv); + scrunch(context->originalIV, iv); + + /* Precompute key schedule */ + + deskey(context->subkeys, key, encrypt); +} + +/* DES-CBC block update operation. Continues a DES-CBC encryption + operation, processing eight-byte message blocks, and updating + the context. + + This requires len to be a multiple of 8. +*/ +int DES_CBCUpdate(context, output, input, len) +DES_CBC_CTX *context; /* context */ +unsigned char *output; /* output block */ +unsigned char *input; /* input block */ +unsigned int len; /* length of input and output blocks */ +{ + UINT4 inputBlock[2], work[2]; + unsigned int i; + + if(len % 8) /* block size check */ + return(RE_LEN); + + for(i = 0; i < len/8; i++) { + scrunch(inputBlock, &input[8*i]); + + /* Chain if encrypting. */ + + if(context->encrypt == 0) { + *work = *inputBlock; + *(work+1) = *(inputBlock+1); + }else{ + *work = *inputBlock ^ *context->iv; + *(work+1) = *(inputBlock+1) ^ *(context->iv+1); + } + + desfunc(work, context->subkeys); + + /* Chain if decrypting, then update IV. */ + + if(context->encrypt == 0) { + *work ^= *context->iv; + *(work+1) ^= *(context->iv+1); + *context->iv = *inputBlock; + *(context->iv+1) = *(inputBlock+1); + }else{ + *context->iv = *work; + *(context->iv+1) = *(work+1); + } + unscrunch (&output[8*i], work); + } + + /* Clear sensitive information. */ + + R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); + R_memset((POINTER)work, 0, sizeof(work)); + + return(IDOK); +} + +void DES_CBCRestart(context) +DES_CBC_CTX *context; /* context */ +{ + /* Restore the original IV */ + + *context->iv = *context->originalIV; + *(context->iv+1) = *(context->originalIV+1); +} + +/* Initialize context. Caller should clear the context when finished. + The key has the DES key, input whitener and output whitener concatenated. + This is the RSADSI special DES implementation. +*/ +void DESX_CBCInit(context, key, iv, encrypt) +DESX_CBC_CTX *context; /* context */ +unsigned char *key; /* DES key and whiteners */ +unsigned char *iv; /* DES initializing vector */ +int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ +{ + /* Save encrypt flag to context. */ + + context->encrypt = encrypt; + + /* Pack initializing vector and whiteners into context. */ + + scrunch(context->iv, iv); + scrunch(context->inputWhitener, key + 8); + scrunch(context->outputWhitener, key + 16); + /* Save the IV for use in Restart */ + scrunch(context->originalIV, iv); + + /* Precompute key schedule. */ + + deskey (context->subkeys, key, encrypt); +} + +/* DESX-CBC block update operation. Continues a DESX-CBC encryption + operation, processing eight-byte message blocks, and updating + the context. This is the RSADSI special DES implementation. + + Requires len to a multiple of 8. +*/ + +int DESX_CBCUpdate (context, output, input, len) +DESX_CBC_CTX *context; /* context */ +unsigned char *output; /* output block */ +unsigned char *input; /* input block */ +unsigned int len; /* length of input and output blocks */ +{ + UINT4 inputBlock[2], work[2]; + unsigned int i; + + if(len % 8) /* Length check */ + return(RE_LEN); + + for(i = 0; i < len/8; i++) { + scrunch(inputBlock, &input[8*i]); + + /* Chain if encrypting, and xor with whitener. */ + + if(context->encrypt == 0) { + *work = *inputBlock ^ *context->outputWhitener; + *(work+1) = *(inputBlock+1) ^ *(context->outputWhitener+1); + }else{ + *work = *inputBlock ^ *context->iv ^ *context->inputWhitener; + *(work+1) = *(inputBlock+1) ^ *(context->iv+1) ^ *(context->inputWhitener+1); + } + + desfunc(work, context->subkeys); + + /* Xor with whitener, chain if decrypting, then update IV. */ + + if(context->encrypt == 0) { + *work ^= *context->iv ^ *context->inputWhitener; + *(work+1) ^= *(context->iv+1) ^ *(context->inputWhitener+1); + *(context->iv) = *inputBlock; + *(context->iv+1) = *(inputBlock+1); + }else{ + *work ^= *context->outputWhitener; + *(work+1) ^= *(context->outputWhitener+1); + *context->iv = *work; + *(context->iv+1) = *(work+1); + } + unscrunch(&output[8*i], work); + } + + R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); + R_memset((POINTER)work, 0, sizeof(work)); + + return(IDOK); +} + +void DESX_CBCRestart(context) +DESX_CBC_CTX *context; /* context */ +{ + /* Restore the original IV */ + *context->iv = *context->originalIV; + *(context->iv+1) = *(context->originalIV+1); +} + +/* Initialize context. Caller must zeroize the context when finished. */ + +void DES3_CBCInit(context, key, iv, encrypt) +DES3_CBC_CTX *context; /* context */ +unsigned char *key; /* key */ +unsigned char *iv; /* initializing vector */ +int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ +{ + /* Copy encrypt flag to context. */ + context->encrypt = encrypt; + + /* Pack initializing vector into context. */ + + scrunch(context->iv, iv); + + /* Save the IV for use in Restart */ + scrunch(context->originalIV, iv); + + /* Precompute key schedules. */ + + deskey(context->subkeys[0], encrypt ? key : &key[16], encrypt); + deskey(context->subkeys[1], &key[8], !encrypt); + deskey(context->subkeys[2], encrypt ? &key[16] : key, encrypt); +} + +int DES3_CBCUpdate(context, output, input, len) +DES3_CBC_CTX *context; /* context */ +unsigned char *output; /* output block */ +unsigned char *input; /* input block */ +unsigned int len; /* length of input and output blocks */ +{ + UINT4 inputBlock[2], work[2]; + unsigned int i; + + if(len % 8) /* length check */ + return(RE_LEN); + + for(i = 0; i < len/8; i++) { + scrunch(inputBlock, &input[8*i]); + + /* Chain if encrypting. */ + + if(context->encrypt == 0) { + *work = *inputBlock; + *(work+1) = *(inputBlock+1); + } + else { + *work = *inputBlock ^ *context->iv; + *(work+1) = *(inputBlock+1) ^ *(context->iv+1); + } + + desfunc(work, context->subkeys[0]); + desfunc(work, context->subkeys[1]); + desfunc(work, context->subkeys[2]); + + /* Chain if decrypting, then update IV. */ + + if(context->encrypt == 0) { + *work ^= *context->iv; + *(work+1) ^= *(context->iv+1); + *context->iv = *inputBlock; + *(context->iv+1) = *(inputBlock+1); + } + else { + *context->iv = *work; + *(context->iv+1) = *(work+1); + } + unscrunch(&output[8*i], work); + } + + R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); + R_memset((POINTER)work, 0, sizeof(work)); + + return (0); +} + +void DES3_CBCRestart (context) +DES3_CBC_CTX *context; /* context */ +{ + /* Restore the original IV */ + *context->iv = *context->originalIV; + *(context->iv+1) = *(context->originalIV+1); +} + +void scrunch (into, outof) +UINT4 *into; +unsigned char *outof; +{ + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into++ |= (*outof++ & 0xffL); + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into |= (*outof & 0xffL); +} + +void unscrunch(into, outof) +unsigned char *into; +UINT4 *outof; +{ + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into++ = (unsigned char)( *outof++ & 0xffL); + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into = (unsigned char)( *outof & 0xffL); +} + +/* Compute DES Subkeys */ + +void deskey(subkeys, key, encrypt) +UINT4 subkeys[32]; +unsigned char key[8]; +int encrypt; +{ + UINT4 kn[32]; + int i, j, l, m, n; + unsigned char pc1m[56], pcr[56]; + + for(j = 0; j < 56; j++) { + l = pc1[j]; + m = l & 07; + pc1m[j] = (unsigned char)((key[l >> 3] & bytebit[m]) ? 1 : 0); + } + for(i = 0; i < 16; i++) { + m = i << 1; + n = m + 1; + kn[m] = kn[n] = 0L; + for(j = 0; j < 28; j++) { + l = j + totrot[i]; + if(l < 28) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for(j = 28; j < 56; j++) { + l = j + totrot[i]; + if(l < 56) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for(j = 0; j < 24; j++) { + if(pcr[pc2[j]]) + kn[m] |= bigbyte[j]; + if(pcr[pc2[j+24]]) + kn[n] |= bigbyte[j]; + } + } + cookey(subkeys, kn, encrypt); + +#ifdef DES386 + for(i=0;i < 32;i++) + subkeys[i] <<= 2; +#endif + + R_memset((POINTER)pc1m, 0, sizeof(pc1m)); + R_memset((POINTER)pcr, 0, sizeof(pcr)); + R_memset((POINTER)kn, 0, sizeof(kn)); +} + +static void cookey(subkeys, kn, encrypt) +UINT4 *subkeys; +UINT4 *kn; +int encrypt; +{ + UINT4 *cooked, *raw0, *raw1; + int increment; + unsigned int i; + + raw1 = kn; + cooked = encrypt ? subkeys : &subkeys[30]; + increment = encrypt ? 1 : -3; + + for (i = 0; i < 16; i++, raw1++) { + raw0 = raw1++; + *cooked = (*raw0 & 0x00fc0000L) << 6; + *cooked |= (*raw0 & 0x00000fc0L) << 10; + *cooked |= (*raw1 & 0x00fc0000L) >> 10; + *cooked++ |= (*raw1 & 0x00000fc0L) >> 6; + *cooked = (*raw0 & 0x0003f000L) << 12; + *cooked |= (*raw0 & 0x0000003fL) << 16; + *cooked |= (*raw1 & 0x0003f000L) >> 4; + *cooked |= (*raw1 & 0x0000003fL); + cooked += increment; + } +} + +#ifndef DES386 /* ignore C version in favor of 386 ONLY desfunc */ + +#define F(l,r,key){\ + work = ((r >> 4) | (r << 28)) ^ *key;\ + l ^= Spbox[6][work & 0x3f];\ + l ^= Spbox[4][(work >> 8) & 0x3f];\ + l ^= Spbox[2][(work >> 16) & 0x3f];\ + l ^= Spbox[0][(work >> 24) & 0x3f];\ + work = r ^ *(key+1);\ + l ^= Spbox[7][work & 0x3f];\ + l ^= Spbox[5][(work >> 8) & 0x3f];\ + l ^= Spbox[3][(work >> 16) & 0x3f];\ + l ^= Spbox[1][(work >> 24) & 0x3f];\ +} + +/* This desfunc code is marginally quicker than that uses in + RSAREF(tm) +*/ + +void desfunc(block,ks) +UINT4 *block; /* Data block */ +UINT4 *ks; /* Key schedule */ +{ + unsigned long left,right,work; + + left = block[0]; + right = block[1]; + + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = (right << 1) | (right >> 31); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 1) | (left >> 31); + + /* Now do the 16 rounds */ + F(left,right,&ks[0]); + F(right,left,&ks[2]); + F(left,right,&ks[4]); + F(right,left,&ks[6]); + F(left,right,&ks[8]); + F(right,left,&ks[10]); + F(left,right,&ks[12]); + F(right,left,&ks[14]); + F(left,right,&ks[16]); + F(right,left,&ks[18]); + F(left,right,&ks[20]); + F(right,left,&ks[22]); + F(left,right,&ks[24]); + F(right,left,&ks[26]); + F(left,right,&ks[28]); + F(right,left,&ks[30]); + + right = (right << 31) | (right >> 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left >> 1) | (left << 31); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; + + *block++ = right; + *block = left; +} + +#endif /* DES386 endif */ diff --git a/source/global.h b/source/global.h old mode 100755 new mode 100644 index ca4141f..c3cbfbb --- a/source/global.h +++ b/source/global.h @@ -1,23 +1,21 @@ /* GLOBAL.H - RSAEURO types and constants - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid + same naming comventions that RSAREF uses. This should aid direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Global types and contants file. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _GLOBAL_H_ diff --git a/source/md2.h b/source/md2.h old mode 100755 new mode 100644 index caf1bd1..6f5264f --- a/source/md2.h +++ b/source/md2.h @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD2 Component Of RSAEURO using RSA Data Security, Inc. MD2 Message Digest Algorithm. diff --git a/source/md2c.c b/source/md2c.c old mode 100755 new mode 100644 index e3c883c..c20965e --- a/source/md2c.c +++ b/source/md2c.c @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD2 Component Of RSAEURO using RSA Data Security, Inc. MD2 Message Digest Algorithm. diff --git a/source/md4.h b/source/md4.h old mode 100755 new mode 100644 index e9b7675..c914fbc --- a/source/md4.h +++ b/source/md4.h @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD4 Component Of RSAEURO using RSA Data Security, Inc. MD4 Message Digest Algorithm. diff --git a/source/md4c.c b/source/md4c.c old mode 100755 new mode 100644 index c12eb56..f64e634 --- a/source/md4c.c +++ b/source/md4c.c @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD4 Component Of RSAEURO using RSA Data Security, Inc. MD4 Message Digest Algorithm. diff --git a/source/md5.h b/source/md5.h old mode 100755 new mode 100644 index 93de216..a0d4547 --- a/source/md5.h +++ b/source/md5.h @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD5 Component Of RSAEURO using RSA Data Security, Inc. MD5 Message Digest Algorithm. diff --git a/source/md5c.c b/source/md5c.c old mode 100755 new mode 100644 index 656c6dc..d826b1e --- a/source/md5c.c +++ b/source/md5c.c @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD5 Component Of RSAEURO using RSA Data Security, Inc. MD5 Message Digest Algorithm. @@ -305,4 +305,4 @@ unsigned int len; for(i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -} \ No newline at end of file +} diff --git a/source/nn.c b/source/nn.c old mode 100755 new mode 100644 index 3c53b8d..af08ef9 --- a/source/nn.c +++ b/source/nn.c @@ -1,675 +1,692 @@ -/* - NN.C - natural numbers routines - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to you applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Revision hisitory - 0.90 First revision, this revision was the basic routines. - Routines slower than final revision. - - 0.91 Second revision, this is the current revision, all - routines have been altered for speed increases. Also the - addition of assembler equivalents. -*/ - -#include "rsaeuro.h" -#include "nn.h" - -/* internal static functions */ - -static NN_DIGIT subdigitmult PROTO_LIST - ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); - -static void dmult PROTO_LIST ((NN_DIGIT, NN_DIGIT, NN_DIGIT *, NN_DIGIT *)); - -static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT)); - -#ifndef USEASM -/* Decodes character string b into a, where character string is ordered - from most to least significant. - - Lengths: a[digits], b[len]. - Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most - significant bytes are truncated.) - */ -void NN_Decode (a, digits, b, len) -NN_DIGIT *a; -unsigned char *b; -unsigned int digits, len; -{ - NN_DIGIT t; - int j; - unsigned int i, u; - - for (i = 0, j = len - 1; i < digits && j >= 0; i++) { - t = 0; - for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) - t |= ((NN_DIGIT)b[j]) << u; - a[i] = t; - } - - for (; i < digits; i++) - a[i] = 0; -} - -/* Encodes b into character string a, where character string is ordered - from most to least significant. - - Lengths: a[len], b[digits]. - Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant - digits are truncated.) - */ -void NN_Encode (a, len, b, digits) -NN_DIGIT *b; -unsigned char *a; -unsigned int digits, len; -{ - NN_DIGIT t; - int j; - unsigned int i, u; - - for (i = 0, j = len - 1; i < digits && j >= 0; i++) { - t = b[i]; - for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) - a[j] = (unsigned char)(t >> u); - } - - for (; j >= 0; j--) - a[j] = 0; -} - -/* Assigns a = 0. */ - -void NN_AssignZero (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - if(digits) { - do { - *a++ = 0; - }while(--digits); - } -} - -#endif - -/* Assigns a = 2^b. - - Lengths: a[digits]. - Requires b < digits * NN_DIGIT_BITS. - */ -void NN_Assign2Exp (a, b, digits) -NN_DIGIT *a; -unsigned int b, digits; -{ - NN_AssignZero (a, digits); - - if (b >= digits * NN_DIGIT_BITS) - return; - - a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS); -} - -/* Computes a = b - c. Returns borrow. - - Lengths: a[digits], b[digits], c[digits]. - */ -NN_DIGIT NN_Sub (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT temp, borrow = 0; - - if(digits) - do { - if((temp = (*b++) - borrow) == MAX_NN_DIGIT) - temp = MAX_NN_DIGIT - *c++; - else - if((temp -= *c) > (MAX_NN_DIGIT - *c++)) - borrow = 1; - else - borrow = 0; - *a++ = temp; - }while(--digits); - - return(borrow); -} - -/* Computes a = b * c. - - Lengths: a[2*digits], b[digits], c[digits]. - Assumes digits < MAX_NN_DIGITS. -*/ - -void NN_Mult (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT t[2*MAX_NN_DIGITS]; - NN_DIGIT dhigh, dlow, carry; - unsigned int bDigits, cDigits, i, j; - - NN_AssignZero (t, 2 * digits); - - bDigits = NN_Digits (b, digits); - cDigits = NN_Digits (c, digits); - - for (i = 0; i < bDigits; i++) { - carry = 0; - if(*(b+i) != 0) { - for(j = 0; j < cDigits; j++) { - dmult(*(b+i), *(c+j), &dhigh, &dlow); - if((*(t+(i+j)) = *(t+(i+j)) + carry) < carry) - carry = 1; - else - carry = 0; - if((*(t+(i+j)) += dlow) < dlow) - carry++; - carry += dhigh; - } - } - *(t+(i+cDigits)) += carry; - } - - - NN_Assign(a, t, 2 * digits); -} - -/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. - - Requires c < NN_DIGIT_BITS. */ - -NN_DIGIT NN_LShift (a, b, c, digits) -NN_DIGIT *a, *b; -unsigned int c, digits; -{ - NN_DIGIT temp, carry = 0; - unsigned int t; - - if(c < NN_DIGIT_BITS) - if(digits) { - - t = NN_DIGIT_BITS - c; - - do { - temp = *b++; - *a++ = (temp << c) | carry; - carry = c ? (temp >> t) : 0; - }while(--digits); - } - - return (carry); -} - -/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. - - Requires: c < NN_DIGIT_BITS. */ - -NN_DIGIT NN_RShift (a, b, c, digits) -NN_DIGIT *a, *b; -unsigned int c, digits; -{ - NN_DIGIT temp, carry = 0; - unsigned int t; - - if(c < NN_DIGIT_BITS) - if(digits) { - - t = NN_DIGIT_BITS - c; - - do { - digits--; - temp = *(b+digits); - *(a+digits) = (temp >> c) | carry; - carry = c ? (temp << t) : 0; - }while(digits); - } - - return (carry); -} - -/* Computes a = c div d and b = c mod d. - - Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. - Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, - dDigits < MAX_NN_DIGITS. -*/ - -void NN_Div (a, b, c, cDigits, d, dDigits) -NN_DIGIT *a, *b, *c, *d; -unsigned int cDigits, dDigits; -{ - NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], s; - NN_DIGIT t[2], u, v, *ccptr; - NN_HALF_DIGIT aHigh, aLow, cHigh, cLow; - int i; - unsigned int ddDigits, shift; - - ddDigits = NN_Digits (d, dDigits); - if(ddDigits == 0) - return; - - shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); - NN_AssignZero (cc, ddDigits); - cc[cDigits] = NN_LShift (cc, c, shift, cDigits); - NN_LShift (dd, d, shift, ddDigits); - s = dd[ddDigits-1]; - - NN_AssignZero (a, cDigits); - - for (i = cDigits-ddDigits; i >= 0; i--) { - if (s == MAX_NN_DIGIT) - ai = cc[i+ddDigits]; - else { - ccptr = &cc[i+ddDigits-1]; - - s++; - cHigh = (NN_HALF_DIGIT)HIGH_HALF (s); - cLow = (NN_HALF_DIGIT)LOW_HALF (s); - - *t = *ccptr; - *(t+1) = *(ccptr+1); - - if (cHigh == MAX_NN_HALF_DIGIT) - aHigh = (NN_HALF_DIGIT)HIGH_HALF (*(t+1)); - else - aHigh = (NN_HALF_DIGIT)(*(t+1) / (cHigh + 1)); - u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow; - v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh; - if ((*t -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u))) - t[1]--; - *(t+1) -= HIGH_HALF (u); - *(t+1) -= v; - - while ((*(t+1) > cHigh) || - ((*(t+1) == cHigh) && (*t >= TO_HIGH_HALF (cLow)))) { - if ((*t -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow)) - t[1]--; - *(t+1) -= cHigh; - aHigh++; - } - - if (cHigh == MAX_NN_HALF_DIGIT) - aLow = (NN_HALF_DIGIT)LOW_HALF (*(t+1)); - else - aLow = - (NN_HALF_DIGIT)((TO_HIGH_HALF (*(t+1)) + HIGH_HALF (*t)) / (cHigh + 1)); - u = (NN_DIGIT)aLow * (NN_DIGIT)cLow; - v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh; - if ((*t -= u) > (MAX_NN_DIGIT - u)) - t[1]--; - if ((*t -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v))) - t[1]--; - *(t+1) -= HIGH_HALF (v); - - while ((*(t+1) > 0) || ((*(t+1) == 0) && *t >= s)) { - if ((*t -= s) > (MAX_NN_DIGIT - s)) - t[1]--; - aLow++; - } - - ai = TO_HIGH_HALF (aHigh) + aLow; - s--; - } - - cc[i+ddDigits] -= subdigitmult(&cc[i], &cc[i], ai, dd, ddDigits); - - while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { - ai++; - cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); - } - - a[i] = ai; - } - - NN_AssignZero (b, dDigits); - NN_RShift (b, cc, shift, ddDigits); -} - - -/* Computes a = b mod c. - - Lengths: a[cDigits], b[bDigits], c[cDigits]. - Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS. -*/ -void NN_Mod (a, b, bDigits, c, cDigits) -NN_DIGIT *a, *b, *c; -unsigned int bDigits, cDigits; -{ - NN_DIGIT t[2 * MAX_NN_DIGITS]; - - NN_Div (t, a, b, bDigits, c, cDigits); -} - -/* Computes a = b * c mod d. - - Lengths: a[digits], b[digits], c[digits], d[digits]. - Assumes d > 0, digits < MAX_NN_DIGITS. - */ -void NN_ModMult (a, b, c, d, digits) -NN_DIGIT *a, *b, *c, *d; -unsigned int digits; -{ - NN_DIGIT t[2*MAX_NN_DIGITS]; - - NN_Mult (t, b, c, digits); - NN_Mod (a, t, 2 * digits, d, digits); -} - -/* Computes a = b^c mod d. - - Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. - Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS. - */ -void NN_ModExp (a, b, c, cDigits, d, dDigits) -NN_DIGIT *a, *b, *c, *d; -unsigned int cDigits, dDigits; -{ - NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS]; - int i; - unsigned int ciBits, j, s; - - /* Store b, b^2 mod d, and b^3 mod d. - */ - NN_Assign (bPower[0], b, dDigits); - NN_ModMult (bPower[1], bPower[0], b, d, dDigits); - NN_ModMult (bPower[2], bPower[1], b, d, dDigits); - - NN_ASSIGN_DIGIT (t, 1, dDigits); - - cDigits = NN_Digits (c, cDigits); - for (i = cDigits - 1; i >= 0; i--) { - ci = c[i]; - ciBits = NN_DIGIT_BITS; - - /* Scan past leading zero bits of most significant digit. - */ - if (i == (int)(cDigits - 1)) { - while (! DIGIT_2MSB (ci)) { - ci <<= 2; - ciBits -= 2; - } - } - - for (j = 0; j < ciBits; j += 2, ci <<= 2) { - /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. */ - NN_ModMult (t, t, t, d, dDigits); - NN_ModMult (t, t, t, d, dDigits); - if ((s = DIGIT_2MSB (ci)) != 0) - NN_ModMult (t, t, bPower[s-1], d, dDigits); - } - } - - NN_Assign (a, t, dDigits); -} - -/* Compute a = 1/b mod c, assuming inverse exists. - - Lengths: a[digits], b[digits], c[digits]. - Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS. - */ -void NN_ModInv (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS], - u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS], - v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS]; - int u1Sign; - - /* Apply extended Euclidean algorithm, modified to avoid negative - numbers. - */ - NN_ASSIGN_DIGIT (u1, 1, digits); - NN_AssignZero (v1, digits); - NN_Assign (u3, b, digits); - NN_Assign (v3, c, digits); - u1Sign = 1; - - while (! NN_Zero (v3, digits)) { - NN_Div (q, t3, u3, digits, v3, digits); - NN_Mult (w, q, v1, digits); - NN_Add (t1, u1, w, digits); - NN_Assign (u1, v1, digits); - NN_Assign (v1, t1, digits); - NN_Assign (u3, v3, digits); - NN_Assign (v3, t3, digits); - u1Sign = -u1Sign; - } - - /* Negate result if sign is negative. */ - if (u1Sign < 0) - NN_Sub (a, c, u1, digits); - else - NN_Assign (a, u1, digits); -} - -/* Computes a = gcd(b, c). - - Assumes b > c, digits < MAX_NN_DIGITS. -*/ - -#define iplus1 ( i==2 ? 0 : i+1 ) /* used by Euclid algorithms */ -#define iminus1 ( i==0 ? 2 : i-1 ) /* used by Euclid algorithms */ -#define g(i) ( &(t[i][0]) ) - -void NN_Gcd(a ,b ,c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - short i; - NN_DIGIT t[3][MAX_NN_DIGITS]; - - NN_Assign(g(0), c, digits); - NN_Assign(g(1), b, digits); - - i=1; - - while(!NN_Zero(g(i),digits)) { - NN_Mod(g(iplus1), g(iminus1), digits, g(i), digits); - i = iplus1; - } - - NN_Assign(a , g(iminus1), digits); -} - -/* Returns the significant length of a in bits. - - Lengths: a[digits]. */ - -unsigned int NN_Bits (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - if ((digits = NN_Digits (a, digits)) == 0) - return (0); - - return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1])); -} - -#ifndef USEASM - -/* Returns sign of a - b. */ - -int NN_Cmp (a, b, digits) -NN_DIGIT *a, *b; -unsigned int digits; -{ - - if(digits) { - do { - digits--; - if(*(a+digits) > *(b+digits)) - return(1); - if(*(a+digits) < *(b+digits)) - return(-1); - }while(digits); - } - - return (0); -} - -/* Returns nonzero iff a is zero. */ - -int NN_Zero (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - if(digits) { - do { - if(*a++) - return(0); - }while(--digits); - } - - return (1); -} - -/* Assigns a = b. */ - -void NN_Assign (a, b, digits) -NN_DIGIT *a, *b; -unsigned int digits; -{ - if(digits) { - do { - *a++ = *b++; - }while(--digits); - } -} - -/* Returns the significant length of a in digits. */ - -unsigned int NN_Digits (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - - if(digits) { - digits--; - - do { - if(*(a+digits)) - break; - }while(digits--); - - return(digits + 1); - } - - return(digits); -} - -/* Computes a = b + c. Returns carry. - - Lengths: a[digits], b[digits], c[digits]. - */ -NN_DIGIT NN_Add (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT temp, carry = 0; - - if(digits) - do { - if((temp = (*b++) + carry) < carry) - temp = *c++; - else - if((temp += *c) < *c++) - carry = 1; - else - carry = 0; - *a++ = temp; - }while(--digits); - - return (carry); -} - -#endif - -static NN_DIGIT subdigitmult(a, b, c, d, digits) -NN_DIGIT *a, *b, c, *d; -unsigned int digits; -{ - NN_DIGIT borrow, thigh, tlow; - unsigned int i; - - borrow = 0; - - if(c != 0) { - for(i = 0; i < digits; i++) { - dmult(c, d[i], &thigh, &tlow); - if((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) - borrow = 1; - else - borrow = 0; - if((a[i] -= tlow) > (MAX_NN_DIGIT - tlow)) - borrow++; - borrow += thigh; - } - } - - return (borrow); -} - -/* Returns the significant length of a in bits, where a is a digit. */ - -static unsigned int NN_DigitBits (a) -NN_DIGIT a; -{ - unsigned int i; - - for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1) - if (a == 0) - break; - - return (i); -} - -/* Computes a * b, result stored in high and low. */ - -static void dmult( a, b, high, low) -NN_DIGIT a, b; -NN_DIGIT *high; -NN_DIGIT *low; -{ - NN_HALF_DIGIT al, ah, bl, bh; - NN_DIGIT m1, m2, m, ml, mh, carry = 0; - - al = (NN_HALF_DIGIT)LOW_HALF(a); - ah = (NN_HALF_DIGIT)HIGH_HALF(a); - bl = (NN_HALF_DIGIT)LOW_HALF(b); - bh = (NN_HALF_DIGIT)HIGH_HALF(b); - - *low = (NN_DIGIT) al*bl; - *high = (NN_DIGIT) ah*bh; - - m1 = (NN_DIGIT) al*bh; - m2 = (NN_DIGIT) ah*bl; - m = m1 + m2; - - if(m < m1) - carry = 1L << (NN_DIGIT_BITS / 2); - - ml = (m & MAX_NN_HALF_DIGIT) << (NN_DIGIT_BITS / 2); - mh = m >> (NN_DIGIT_BITS / 2); - - *low += ml; - - if(*low < ml) - carry++; - - *high += carry + mh; -} - +/* + NN.C - natural numbers routines + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to you applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Revision hisitory + 0.90 First revision, this revision was the basic routines. + Routines slower than final revision. + + 0.91 Second revision, this is the current revision, all + routines have been altered for speed increases. Also the + addition of assembler equivalents. + + 1.02 Third revision, minor bug fixes. + dmult bug fix, Bug reported by Anders Heerfordt . + + 1.03 Fourth revision, SunCompiler patch +*/ + +#include "rsaeuro.h" +#include "nn.h" + +/* internal static functions */ + +static NN_DIGIT subdigitmult PROTO_LIST + ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); + +static void dmult PROTO_LIST ((NN_DIGIT, NN_DIGIT, NN_DIGIT *, NN_DIGIT *)); + +static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT)); + +#ifndef USEASM +/* Decodes character string b into a, where character string is ordered + from most to least significant. + + Lengths: a[digits], b[len]. + Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most + significant bytes are truncated.) + */ +void NN_Decode (a, digits, b, len) +NN_DIGIT *a; +unsigned char *b; +unsigned int digits, len; +{ + NN_DIGIT t; + unsigned int i, j, u; + + for (i = 0, j = len - 1; i < digits && j >= 0; i++) { + t = 0; + for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) + t |= ((NN_DIGIT)b[j]) << u; + a[i] = t; + } + + for (; i < digits; i++) + a[i] = 0; +} + +/* Encodes b into character string a, where character string is ordered + from most to least significant. + + Lengths: a[len], b[digits]. + Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant + digits are truncated.) + */ +void NN_Encode (a, len, b, digits) +NN_DIGIT *b; +unsigned char *a; +unsigned int digits, len; +{ + NN_DIGIT t; + unsigned int i, j, u; + + for (i = 0, j = len - 1; i < digits && j >= 0; i++) { + t = b[i]; + for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) + a[j] = (unsigned char)(t >> u); + } + + for (; j >= 0; j--) + a[j] = 0; +} + +/* Assigns a = 0. */ + +void NN_AssignZero (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + if(digits) { + do { + *a++ = 0; + }while(--digits); + } +} + +#endif + +/* Assigns a = 2^b. + + Lengths: a[digits]. + Requires b < digits * NN_DIGIT_BITS. + */ +void NN_Assign2Exp (a, b, digits) +NN_DIGIT *a; +unsigned int b, digits; +{ + NN_AssignZero (a, digits); + + if (b >= digits * NN_DIGIT_BITS) + return; + + a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS); +} + +/* Computes a = b - c. Returns borrow. + + Lengths: a[digits], b[digits], c[digits]. + */ +NN_DIGIT NN_Sub (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT temp, borrow = 0; + + if(digits) + do { + /* Bug fix 16/10/95 - JSK, code below removed, caused bug with + Sun Compiler SC4. + + if((temp = (*b++) - borrow) == MAX_NN_DIGIT) + temp = MAX_NN_DIGIT - *c++; + */ + + temp = *b - borrow; + b++; + if(temp == MAX_NN_DIGIT) { + temp = MAX_NN_DIGIT - *c; + c++; + }else { /* Patch to prevent bug for Sun CC */ + if((temp -= *c) > (MAX_NN_DIGIT - *c)) + borrow = 1; + else + borrow = 0; + c++; + } + *a++ = temp; + }while(--digits); + + return(borrow); +} + +/* Computes a = b * c. + + Lengths: a[2*digits], b[digits], c[digits]. + Assumes digits < MAX_NN_DIGITS. +*/ + +void NN_Mult (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT t[2*MAX_NN_DIGITS]; + NN_DIGIT dhigh, dlow, carry; + unsigned int bDigits, cDigits, i, j; + + NN_AssignZero (t, 2 * digits); + + bDigits = NN_Digits (b, digits); + cDigits = NN_Digits (c, digits); + + for (i = 0; i < bDigits; i++) { + carry = 0; + if(*(b+i) != 0) { + for(j = 0; j < cDigits; j++) { + dmult(*(b+i), *(c+j), &dhigh, &dlow); + if((*(t+(i+j)) = *(t+(i+j)) + carry) < carry) + carry = 1; + else + carry = 0; + if((*(t+(i+j)) += dlow) < dlow) + carry++; + carry += dhigh; + } + } + *(t+(i+cDigits)) += carry; + } + + + NN_Assign(a, t, 2 * digits); +} + +/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. + + Requires c < NN_DIGIT_BITS. */ + +NN_DIGIT NN_LShift (a, b, c, digits) +NN_DIGIT *a, *b; +unsigned int c, digits; +{ + NN_DIGIT temp, carry = 0; + unsigned int t; + + if(c < NN_DIGIT_BITS) + if(digits) { + + t = NN_DIGIT_BITS - c; + + do { + temp = *b++; + *a++ = (temp << c) | carry; + carry = c ? (temp >> t) : 0; + }while(--digits); + } + + return (carry); +} + +/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. + + Requires: c < NN_DIGIT_BITS. */ + +NN_DIGIT NN_RShift (a, b, c, digits) +NN_DIGIT *a, *b; +unsigned int c, digits; +{ + NN_DIGIT temp, carry = 0; + unsigned int t; + + if(c < NN_DIGIT_BITS) + if(digits) { + + t = NN_DIGIT_BITS - c; + + do { + digits--; + temp = *(b+digits); + *(a+digits) = (temp >> c) | carry; + carry = c ? (temp << t) : 0; + }while(digits); + } + + return (carry); +} + +/* Computes a = c div d and b = c mod d. + + Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. + Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, + dDigits < MAX_NN_DIGITS. +*/ + +void NN_Div (a, b, c, cDigits, d, dDigits) +NN_DIGIT *a, *b, *c, *d; +unsigned int cDigits, dDigits; +{ + NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], s; + NN_DIGIT t[2], u, v, *ccptr; + NN_HALF_DIGIT aHigh, aLow, cHigh, cLow; + int i; + unsigned int ddDigits, shift; + + ddDigits = NN_Digits (d, dDigits); + if(ddDigits == 0) + return; + + shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); + NN_AssignZero (cc, ddDigits); + cc[cDigits] = NN_LShift (cc, c, shift, cDigits); + NN_LShift (dd, d, shift, ddDigits); + s = dd[ddDigits-1]; + + NN_AssignZero (a, cDigits); + + for (i = cDigits-ddDigits; i >= 0; i--) { + if (s == MAX_NN_DIGIT) + ai = cc[i+ddDigits]; + else { + ccptr = &cc[i+ddDigits-1]; + + s++; + cHigh = (NN_HALF_DIGIT)HIGH_HALF (s); + cLow = (NN_HALF_DIGIT)LOW_HALF (s); + + *t = *ccptr; + *(t+1) = *(ccptr+1); + + if (cHigh == MAX_NN_HALF_DIGIT) + aHigh = (NN_HALF_DIGIT)HIGH_HALF (*(t+1)); + else + aHigh = (NN_HALF_DIGIT)(*(t+1) / (cHigh + 1)); + u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow; + v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh; + if ((*t -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u))) + t[1]--; + *(t+1) -= HIGH_HALF (u); + *(t+1) -= v; + + while ((*(t+1) > cHigh) || + ((*(t+1) == cHigh) && (*t >= TO_HIGH_HALF (cLow)))) { + if ((*t -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow)) + t[1]--; + *(t+1) -= cHigh; + aHigh++; + } + + if (cHigh == MAX_NN_HALF_DIGIT) + aLow = (NN_HALF_DIGIT)LOW_HALF (*(t+1)); + else + aLow = + (NN_HALF_DIGIT)((TO_HIGH_HALF (*(t+1)) + HIGH_HALF (*t)) / (cHigh + 1)); + u = (NN_DIGIT)aLow * (NN_DIGIT)cLow; + v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh; + if ((*t -= u) > (MAX_NN_DIGIT - u)) + t[1]--; + if ((*t -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v))) + t[1]--; + *(t+1) -= HIGH_HALF (v); + + while ((*(t+1) > 0) || ((*(t+1) == 0) && *t >= s)) { + if ((*t -= s) > (MAX_NN_DIGIT - s)) + t[1]--; + aLow++; + } + + ai = TO_HIGH_HALF (aHigh) + aLow; + s--; + } + + cc[i+ddDigits] -= subdigitmult(&cc[i], &cc[i], ai, dd, ddDigits); + + while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { + ai++; + cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); + } + + a[i] = ai; + } + + NN_AssignZero (b, dDigits); + NN_RShift (b, cc, shift, ddDigits); +} + + +/* Computes a = b mod c. + + Lengths: a[cDigits], b[bDigits], c[cDigits]. + Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS. +*/ +void NN_Mod (a, b, bDigits, c, cDigits) +NN_DIGIT *a, *b, *c; +unsigned int bDigits, cDigits; +{ + NN_DIGIT t[2 * MAX_NN_DIGITS]; + + NN_Div (t, a, b, bDigits, c, cDigits); +} + +/* Computes a = b * c mod d. + + Lengths: a[digits], b[digits], c[digits], d[digits]. + Assumes d > 0, digits < MAX_NN_DIGITS. + */ +void NN_ModMult (a, b, c, d, digits) +NN_DIGIT *a, *b, *c, *d; +unsigned int digits; +{ + NN_DIGIT t[2*MAX_NN_DIGITS]; + + NN_Mult (t, b, c, digits); + NN_Mod (a, t, 2 * digits, d, digits); +} + +/* Computes a = b^c mod d. + + Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. + Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS. + */ +void NN_ModExp (a, b, c, cDigits, d, dDigits) +NN_DIGIT *a, *b, *c, *d; +unsigned int cDigits, dDigits; +{ + NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS]; + int i; + unsigned int ciBits, j, s; + + /* Store b, b^2 mod d, and b^3 mod d. + */ + NN_Assign (bPower[0], b, dDigits); + NN_ModMult (bPower[1], bPower[0], b, d, dDigits); + NN_ModMult (bPower[2], bPower[1], b, d, dDigits); + + NN_ASSIGN_DIGIT (t, 1, dDigits); + + cDigits = NN_Digits (c, cDigits); + for (i = cDigits - 1; i >= 0; i--) { + ci = c[i]; + ciBits = NN_DIGIT_BITS; + + /* Scan past leading zero bits of most significant digit. + */ + if (i == (int)(cDigits - 1)) { + while (! DIGIT_2MSB (ci)) { + ci <<= 2; + ciBits -= 2; + } + } + + for (j = 0; j < ciBits; j += 2, ci <<= 2) { + /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. */ + NN_ModMult (t, t, t, d, dDigits); + NN_ModMult (t, t, t, d, dDigits); + if ((s = DIGIT_2MSB (ci)) != 0) + NN_ModMult (t, t, bPower[s-1], d, dDigits); + } + } + + NN_Assign (a, t, dDigits); +} + +/* Compute a = 1/b mod c, assuming inverse exists. + + Lengths: a[digits], b[digits], c[digits]. + Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS. + */ +void NN_ModInv (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS], + u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS], + v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS]; + int u1Sign; + + /* Apply extended Euclidean algorithm, modified to avoid negative + numbers. + */ + NN_ASSIGN_DIGIT (u1, 1, digits); + NN_AssignZero (v1, digits); + NN_Assign (u3, b, digits); + NN_Assign (v3, c, digits); + u1Sign = 1; + + while (! NN_Zero (v3, digits)) { + NN_Div (q, t3, u3, digits, v3, digits); + NN_Mult (w, q, v1, digits); + NN_Add (t1, u1, w, digits); + NN_Assign (u1, v1, digits); + NN_Assign (v1, t1, digits); + NN_Assign (u3, v3, digits); + NN_Assign (v3, t3, digits); + u1Sign = -u1Sign; + } + + /* Negate result if sign is negative. */ + if (u1Sign < 0) + NN_Sub (a, c, u1, digits); + else + NN_Assign (a, u1, digits); +} + +/* Computes a = gcd(b, c). + + Assumes b > c, digits < MAX_NN_DIGITS. +*/ + +#define iplus1 ( i==2 ? 0 : i+1 ) /* used by Euclid algorithms */ +#define iminus1 ( i==0 ? 2 : i-1 ) /* used by Euclid algorithms */ +#define g(i) ( &(t[i][0]) ) + +void NN_Gcd(a ,b ,c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + short i; + NN_DIGIT t[3][MAX_NN_DIGITS]; + + NN_Assign(g(0), c, digits); + NN_Assign(g(1), b, digits); + + i=1; + + while(!NN_Zero(g(i),digits)) { + NN_Mod(g(iplus1), g(iminus1), digits, g(i), digits); + i = iplus1; + } + + NN_Assign(a , g(iminus1), digits); +} + +/* Returns the significant length of a in bits. + + Lengths: a[digits]. */ + +unsigned int NN_Bits (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + if ((digits = NN_Digits (a, digits)) == 0) + return (0); + + return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1])); +} + +#ifndef USEASM + +/* Returns sign of a - b. */ + +int NN_Cmp (a, b, digits) +NN_DIGIT *a, *b; +unsigned int digits; +{ + + if(digits) { + do { + digits--; + if(*(a+digits) > *(b+digits)) + return(1); + if(*(a+digits) < *(b+digits)) + return(-1); + }while(digits); + } + + return (0); +} + +/* Returns nonzero iff a is zero. */ + +int NN_Zero (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + if(digits) { + do { + if(*a++) + return(0); + }while(--digits); + } + + return (1); +} + +/* Assigns a = b. */ + +void NN_Assign (a, b, digits) +NN_DIGIT *a, *b; +unsigned int digits; +{ + if(digits) { + do { + *a++ = *b++; + }while(--digits); + } +} + +/* Returns the significant length of a in digits. */ + +unsigned int NN_Digits (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + + if(digits) { + digits--; + + do { + if(*(a+digits)) + break; + }while(digits--); + + return(digits + 1); + } + + return(digits); +} + +/* Computes a = b + c. Returns carry. + + Lengths: a[digits], b[digits], c[digits]. + */ +NN_DIGIT NN_Add (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT temp, carry = 0; + + if(digits) + do { + if((temp = (*b++) + carry) < carry) + temp = *c++; + else { /* Patch to prevent bug for Sun CC */ + if((temp += *c) < *c) + carry = 1; + else + carry = 0; + c++; + } + *a++ = temp; + }while(--digits); + + return (carry); +} + +#endif + +static NN_DIGIT subdigitmult(a, b, c, d, digits) +NN_DIGIT *a, *b, c, *d; +unsigned int digits; +{ + NN_DIGIT borrow, thigh, tlow; + unsigned int i; + + borrow = 0; + + if(c != 0) { + for(i = 0; i < digits; i++) { + dmult(c, d[i], &thigh, &tlow); + if((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) + borrow = 1; + else + borrow = 0; + if((a[i] -= tlow) > (MAX_NN_DIGIT - tlow)) + borrow++; + borrow += thigh; + } + } + + return (borrow); +} + +/* Returns the significant length of a in bits, where a is a digit. */ + +static unsigned int NN_DigitBits (a) +NN_DIGIT a; +{ + unsigned int i; + + for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1) + if (a == 0) + break; + + return (i); +} + +/* Computes a * b, result stored in high and low. */ + +static void dmult( a, b, high, low) +NN_DIGIT a, b; +NN_DIGIT *high; +NN_DIGIT *low; +{ + NN_HALF_DIGIT al, ah, bl, bh; + NN_DIGIT m1, m2, m, ml, mh, carry = 0; + + al = (NN_HALF_DIGIT)LOW_HALF(a); + ah = (NN_HALF_DIGIT)HIGH_HALF(a); + bl = (NN_HALF_DIGIT)LOW_HALF(b); + bh = (NN_HALF_DIGIT)HIGH_HALF(b); + + *low = (NN_DIGIT) al*bl; + *high = (NN_DIGIT) ah*bh; + + m1 = (NN_DIGIT) al*bh; + m2 = (NN_DIGIT) ah*bl; + m = m1 + m2; + + if(m < m1) + carry = 1L << (NN_DIGIT_BITS / 2); + + ml = (m & MAX_NN_HALF_DIGIT) << (NN_DIGIT_BITS / 2); + mh = m >> (NN_DIGIT_BITS / 2); + + *low += ml; + + if(*low < ml) + carry++; + + *high += carry + mh; +} + diff --git a/source/nn.h b/source/nn.h old mode 100755 new mode 100644 index 09b1e62..03b7b61 --- a/source/nn.h +++ b/source/nn.h @@ -1,23 +1,21 @@ /* NN.H - header file for NN.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Math Library Routines Header File. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _NN_H_ diff --git a/source/prime.c b/source/prime.c old mode 100755 new mode 100644 index bf9ace6..f671253 --- a/source/prime.c +++ b/source/prime.c @@ -1,285 +1,285 @@ -/* - PRIME.C - primality-testing routines - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Uses a small primes factor test and the Fermat Test to determine if - the number is probable prime number. - - Future Version may use Radin-Miller Primes Test? - - Revision history - 0.90 First revision, produced to perform just like the - RSAREF(tm) version. - - 0.91 Second revision, modified probableprime routine with - some major revisions. Added large small primes table for - small primes test, altered flow of small primes test. Results - produced a huge speed increase using REDEMO, upwards of 70% - speed increase (1024 bit keys). -*/ - -#include "rsaeuro.h" -#include "r_random.h" -#include "nn.h" -#include "prime.h" - -#define SMALL_PRIME_COUNT 1027 - -static int probableprime PROTO_LIST ((NN_DIGIT *, unsigned int)); - -/* Generates a probable prime a between b and c such that a-1 is - divisible by d. - - Assumes b < c, digits < MAX_NN_DIGITS. - Returns RE_NEED_RANDOM if randomStruct not seeded, RE_DATA if - unsuccessful. -*/ - -int GeneratePrime(a, b, c, d, digits, randomStruct) -NN_DIGIT *a, *b, *c, *d; -unsigned int digits; -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - int status; - unsigned char block[MAX_NN_DIGITS * NN_DIGIT_LEN]; - NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; - - /* Generate random number between b and c. */ - - status = R_GenerateBytes(block, digits * NN_DIGIT_LEN, randomStruct); - if(status) - return(status); - - NN_Decode(a, digits, block, digits * NN_DIGIT_LEN); - NN_Sub(t, c, b, digits); - NN_ASSIGN_DIGIT(u, 1, digits); - NN_Add(t, t, u, digits); - NN_Mod(a, a, digits, t, digits); - NN_Add(a, a, b, digits); - - /* Adjust so that a-1 is divisible by d. */ - - NN_Mod(t, a, digits, d, digits); - NN_Sub(a, a, t, digits); - NN_Add(a, a, u, digits); - if(NN_Cmp(a, b, digits) < 0) - NN_Add(a, a, d, digits); - if(NN_Cmp(a, c, digits) > 0) - NN_Sub(a, a, d, digits); - - /* Search to c in steps of d. */ - - NN_Assign(t, c, digits); - NN_Sub(t, t, d, digits); - - while(!probableprime (a, digits)) { - if(NN_Cmp (a, t, digits) > 0) - return(RE_DATA); - NN_Add(a, a, d, digits); - } - - return(IDOK); -} - -/* Returns nonzero iff a is a probable prime. - - Does small factor test and a fermat test witness 2. -*/ - -static int probableprime(a, aDigits) -NN_DIGIT *a; -unsigned int aDigits; -{ - - int status; - NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; - /* This table can be reduced in size but the smaller - the table the slower the testing. - */ - static unsigned int SMALL_PRIMES[] = { - 3, 5, 7, 11, 13, 17, 19, - 23, 29, 31, 37, 41, 43, 47, 53, - 59, 61, 67, 71, 73, 79, 83, 89, - 97, 101, 103, 107, 109, 113, 127, 131, - 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, - 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, - 313, 317, 331, 337, 347, 349, 353, 359, - 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, - 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, - 571, 577, 587, 593, 599, 601, 607, 613, - 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, - 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, - 829, 839, 853, 857, 859, 863, 877, 881, - 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, - 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, - 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, - 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, - 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, - 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, - 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, - 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, - 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, - 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, - 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, - 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, - 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, - 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, - 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, - 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, - 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, - 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, - 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, - 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, - 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, - 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, - 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, - 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, - 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, - 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, - 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, - 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, - 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, - 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, - 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, - 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, - 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, - 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, - 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, - 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, - 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, - 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, - 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, - 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, - 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, - 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, - 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, - 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, - 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, - 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, - 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, - 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, - 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, - 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, - 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, - 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, - 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, - 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, - 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, - 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, - 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, - 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, - 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, - 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, - 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, - 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, - 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, - 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, - 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, - 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, - 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, - 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, - 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, - 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, - 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, - 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, - 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, - 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, - 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, - 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, - 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, - 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, - 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, - 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, - 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, - 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, - 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, - 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, - 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, - 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, - 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, - 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, - 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, - 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, - 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, - 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, - 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, - 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, - 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, - 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, - 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, - 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, - 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, - 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, - 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, - 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, - 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, - 8167, 8171, 8179, 8191, 0 - }; - unsigned int i,x; - - status = 1; - - NN_AssignZero(t, aDigits); - - /* Small Primes test, weed out junk numbers before slower Fermat's */ - - for(i = 0; *(SMALL_PRIMES+i); i++) { - *t = *(SMALL_PRIMES+i); - if(aDigits == 1) - if(NN_Cmp (a, t, 1) == 0) - break; - NN_Mod(t, a, aDigits, t, 1); - if(NN_Zero (t, 1)) { - status = 0; - break; - } - } - - /* Clear sensitive information. */ - - i = 0; - R_memset((POINTER)t, 0, sizeof(t)); - - /* Fermat's test for witness 2. - (All primes pass the test, and nearly all composites fail.) - */ - - if(status) { - NN_ASSIGN_DIGIT(t, 2, aDigits); - NN_ModExp(u, t, a, aDigits, a, aDigits); - - status = NN_EQUAL(t, u, aDigits); - - /* Clear sensitive information. */ - - R_memset((POINTER)u, 0, sizeof(u)); - } - - return(status ? TRUE : FALSE); -} - +/* + PRIME.C - primality-testing routines + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Uses a small primes factor test and the Fermat Test to determine if + the number is probable prime number. + + Future Version may use Radin-Miller Primes Test? + + Revision history + 0.90 First revision, produced to perform just like the + RSAREF(tm) version. + + 0.91 Second revision, modified probableprime routine with + some major revisions. Added large small primes table for + small primes test, altered flow of small primes test. Results + produced a huge speed increase using REDEMO, upwards of 70% + speed increase (1024 bit keys). +*/ + +#include "rsaeuro.h" +#include "r_random.h" +#include "nn.h" +#include "prime.h" + +#define SMALL_PRIME_COUNT 1027 + +static int probableprime PROTO_LIST ((NN_DIGIT *, unsigned int)); + +/* Generates a probable prime a between b and c such that a-1 is + divisible by d. + + Assumes b < c, digits < MAX_NN_DIGITS. + Returns RE_NEED_RANDOM if randomStruct not seeded, RE_DATA if + unsuccessful. +*/ + +int GeneratePrime(a, b, c, d, digits, randomStruct) +NN_DIGIT *a, *b, *c, *d; +unsigned int digits; +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + int status; + unsigned char block[MAX_NN_DIGITS * NN_DIGIT_LEN]; + NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; + + /* Generate random number between b and c. */ + + status = R_GenerateBytes(block, digits * NN_DIGIT_LEN, randomStruct); + if(status) + return(status); + + NN_Decode(a, digits, block, digits * NN_DIGIT_LEN); + NN_Sub(t, c, b, digits); + NN_ASSIGN_DIGIT(u, 1, digits); + NN_Add(t, t, u, digits); + NN_Mod(a, a, digits, t, digits); + NN_Add(a, a, b, digits); + + /* Adjust so that a-1 is divisible by d. */ + + NN_Mod(t, a, digits, d, digits); + NN_Sub(a, a, t, digits); + NN_Add(a, a, u, digits); + if(NN_Cmp(a, b, digits) < 0) + NN_Add(a, a, d, digits); + if(NN_Cmp(a, c, digits) > 0) + NN_Sub(a, a, d, digits); + + /* Search to c in steps of d. */ + + NN_Assign(t, c, digits); + NN_Sub(t, t, d, digits); + + while(!probableprime (a, digits)) { + if(NN_Cmp (a, t, digits) > 0) + return(RE_DATA); + NN_Add(a, a, d, digits); + } + + return(IDOK); +} + +/* Returns nonzero iff a is a probable prime. + + Does small factor test and a fermat test witness 2. +*/ + +static int probableprime(a, aDigits) +NN_DIGIT *a; +unsigned int aDigits; +{ + + int status; + NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; + /* This table can be reduced in size but the smaller + the table the slower the testing. + */ + static unsigned int SMALL_PRIMES[] = { + 3, 5, 7, 11, 13, 17, 19, + 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, + 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, + 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, + 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, + 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, + 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, + 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, + 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, + 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, + 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, + 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, + 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, + 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, + 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, + 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, + 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, + 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, + 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, + 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, + 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, + 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, + 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, + 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, + 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, + 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, + 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, + 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, + 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, + 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, + 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, + 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, + 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, + 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, + 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, + 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, + 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, + 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, + 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, + 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, + 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, + 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, + 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, + 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, + 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, + 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, + 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, + 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, + 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, + 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, + 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, + 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, + 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, + 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, + 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, + 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, + 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, + 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, + 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, + 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, + 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, + 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, + 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, + 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, + 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, + 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, + 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, + 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, + 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, + 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, + 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, + 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, + 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, + 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, + 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, + 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, + 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, + 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, + 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, + 8167, 8171, 8179, 8191, 0 + }; + unsigned int i,x; + + status = 1; + + NN_AssignZero(t, aDigits); + + /* Small Primes test, weed out junk numbers before slower Fermat's */ + + for(i = 0; *(SMALL_PRIMES+i); i++) { + *t = *(SMALL_PRIMES+i); + if(aDigits == 1) + if(NN_Cmp (a, t, 1) == 0) + break; + NN_Mod(t, a, aDigits, t, 1); + if(NN_Zero (t, 1)) { + status = 0; + break; + } + } + + /* Clear sensitive information. */ + + i = 0; + R_memset((POINTER)t, 0, sizeof(t)); + + /* Fermat's test for witness 2. + (All primes pass the test, and nearly all composites fail.) + */ + + if(status) { + NN_ASSIGN_DIGIT(t, 2, aDigits); + NN_ModExp(u, t, a, aDigits, a, aDigits); + + status = NN_EQUAL(t, u, aDigits); + + /* Clear sensitive information. */ + + R_memset((POINTER)u, 0, sizeof(u)); + } + + return(status ? TRUE : FALSE); +} + diff --git a/source/prime.h b/source/prime.h old mode 100755 new mode 100644 index 392d5ed..c030afd --- a/source/prime.h +++ b/source/prime.h @@ -1,23 +1,21 @@ /* PRIME.H - header file for PRIME.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Prime Number routines header file. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ int GeneratePrime PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, R_RANDOM_STRUCT *)); diff --git a/source/r_dh.c b/source/r_dh.c old mode 100755 new mode 100644 index e438f8d..3f09a2e --- a/source/r_dh.c +++ b/source/r_dh.c @@ -2,7 +2,7 @@ R_DH.C - Diffie-Hellman routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -23,7 +23,6 @@ Diffie-Hellman key agreement stuff, based heavily on RSAREF(tm) and relies heavily on the NN.C routines. - 1.00 23/6/95, Final Release Version */ #include "rsaeuro.h" @@ -165,4 +164,4 @@ R_DH_PARAMS *params; /* Diffie-Hellman parameters */ R_memset((POINTER)z, 0, sizeof(z)); return(IDOK); -} \ No newline at end of file +} diff --git a/source/r_encode.c b/source/r_encode.c old mode 100755 new mode 100644 index 69fe820..00030f1 --- a/source/r_encode.c +++ b/source/r_encode.c @@ -1,219 +1,219 @@ -/* - R_ENCODE.C - RFC 1113 encoding and decoding routines - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Based in a similar form to the PGP RFC 1113 coding routines. - - Revision history - 0.90 First revision, based purely on using macros to - en/decode data to RFC 1113 standard. - - 0.91 Initial revision using current system. - - 0.92 Third revision, fixed minor bugs in rev. 0.91 - and better comments updated, plus code layout. - - 1.02 Fourth revision, fixed bug in R_EncodePEMBlock - reported by Wang Wei Jun . -*/ - -#include "rsaeuro.h" - -/* RFC 1113 encoding: - - Value Encoding Value Encoding Value Encoding Value Encoding - 0 A 17 R 34 i 51 z - 1 B 18 S 35 j 52 0 - 2 C 19 T 36 k 53 1 - 3 D 20 U 37 l 54 2 - 4 E 21 V 38 m 55 3 - 5 F 22 W 39 n 56 4 - 6 G 23 X 40 o 57 5 - 7 H 24 Y 41 p 58 6 - 8 I 25 Z 42 q 59 7 - 9 J 26 a 43 r 60 8 - 10 K 27 b 44 s 61 9 - 11 L 28 c 45 t 62 + - 12 M 29 d 46 u 63 / - 13 N 30 e 47 v - 14 O 31 f 48 w (pad) = - 15 P 32 g 49 x - 16 Q 33 h 50 y -*/ - -/* - PEM routines. - This converts a binary file into printable ASCII characters, in a - radix-64 form mostly compatible with the PEM RFC 1113 format. - This makes it easier to send encrypted files over a 7-bit channel. -*/ - -/* ENC is the basic 1 character encoding function to make a char printing */ - -#define ENC(c) ((int)bintoasc[((c) & 077)]) -#define PAD '=' - -/* Index this array by a 6 bit value to get the character corresponding - to that value. */ - -static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ -abcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* Index this array by a 7 bit value to get the 6-bit binary field - corresponding to that value. Any illegal characters return high bit set. */ - -static unsigned char asctobin[] = { - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0076,0200,0200,0200,0077, - 0064,0065,0066,0067,0070,0071,0072,0073, - 0074,0075,0200,0200,0200,0200,0200,0200, - 0200,0000,0001,0002,0003,0004,0005,0006, - 0007,0010,0011,0012,0013,0014,0015,0016, - 0017,0020,0021,0022,0023,0024,0025,0026, - 0027,0030,0031,0200,0200,0200,0200,0200, - 0200,0032,0033,0034,0035,0036,0037,0040, - 0041,0042,0043,0044,0045,0046,0047,0050, - 0051,0052,0053,0054,0055,0056,0057,0060, - 0061,0062,0063,0200,0200,0200,0200,0200 -}; - -static void encode PROTO_LIST((unsigned char [4], unsigned char [3], int )); - -/* This will always returns 0. It is an int function for future compatibility, - done to provide compatibility with RSAREF(tm). */ - -int R_EncodePEMBlock(encodedBlock, encodedBlockLen, block, blockLen) -unsigned char *encodedBlock; /* encoded block */ -unsigned int *encodedBlockLen; /* length of encoded block */ -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -{ - unsigned int i, lastLen; - - if(blockLen < 1) { - *encodedBlockLen = 0; - return (IDOK); - } - - *encodedBlockLen = 0; - - /* Bug Fixed By SK 02/09/95 */ - for (i = 0, lastLen = blockLen; i < blockLen; i += 3) { - encode(&encodedBlock[4*i/3], &block[i], (lastLen >= 3 ? 3 : lastLen)); - lastLen -= 3; - *encodedBlockLen += 4; - } - - return(IDOK); -} - -int R_DecodePEMBlock (outbuf, outlength, inbuf, inlength) -unsigned char *outbuf; /* block */ -unsigned int *outlength; /* length of block */ -unsigned char *inbuf; /* encoded block */ -unsigned int inlength; /* length of encoded block */ -{ - unsigned char *bp; - int length; - unsigned int c1,c2,c3,c4; - register int j; - - if(inlength % 4) - return (RE_ENCODING); - - if(inlength < 1) { - *outlength = 0; - return (IDOK); - } - - - length = 0; - bp = (unsigned char *)inbuf; - - /* FOUR input characters go into each THREE output charcters */ - - while(inlength > 0) { - if(*bp&0x80 || (c1=asctobin[*bp])&0x80) - return(RE_ENCODING); - ++bp; - if(*bp&0x80 || (c2=asctobin[*bp])&0x80) - return(RE_ENCODING); - if(*++bp == PAD){ - c3 = c4 = 0; - length += 1; - if(*++bp != PAD) - return(RE_ENCODING); - } - else if(*bp&0x80 || (c3=asctobin[*bp])&0x80) - return(RE_ENCODING); - else { - if(*++bp == PAD) { - c4 = 0; - length += 2; - } - else if (*bp&0x80 || (c4=asctobin[*bp])&0x80) - return(RE_ENCODING); - else - length += 3; - } - ++bp; - j = (c1 << 2) | (c2 >> 4); - *outbuf++=j; - j = (c2 << 4) | (c3 >> 2); - *outbuf++=j; - j = (c3 << 6) | c4; - *outbuf++=j; - inlength -= 4; - } - - *outlength = length; - return(IDOK); /* normal return */ - -} - -/* - Output one group of up to 3 bytes, pointed at by p, to buffer at f. - If fewer than 3 are present, the 1 or two extras must be zeros. -*/ - -static void encode(f, p, count) -unsigned char *f; /* output buffer */ -unsigned char *p; /* input buffer */ -int count; /* count */ -{ - int c1, c2, c3, c4; - - c1 = *p >> 2; - c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017); - c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); - c4 = p[2] & 077; - *f++ = ENC(c1); - *f++ = ENC(c2); - if (count == 1) - { - *f++ = PAD; - *f++ = PAD; - }else{ - *f++ = ENC(c3); - if(count == 2) *f++ = PAD; - else *f++ = ENC(c4); - } -} - +/* + R_ENCODE.C - RFC 1113 encoding and decoding routines + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Based in a similar form to the PGP RFC 1113 coding routines. + + Revision history + 0.90 First revision, based purely on using macros to + en/decode data to RFC 1113 standard. + + 0.91 Initial revision using current system. + + 0.92 Third revision, fixed minor bugs in rev. 0.91 + and better comments updated, plus code layout. + + 1.02 Fourth revision, fixed bug in R_EncodePEMBlock + reported by Wang Wei Jun . +*/ + +#include "rsaeuro.h" + +/* RFC 1113 encoding: + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y +*/ + +/* + PEM routines. + This converts a binary file into printable ASCII characters, in a + radix-64 form mostly compatible with the PEM RFC 1113 format. + This makes it easier to send encrypted files over a 7-bit channel. +*/ + +/* ENC is the basic 1 character encoding function to make a char printing */ + +#define ENC(c) ((int)bintoasc[((c) & 077)]) +#define PAD '=' + +/* Index this array by a 6 bit value to get the character corresponding + to that value. */ + +static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ +abcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Index this array by a 7 bit value to get the 6-bit binary field + corresponding to that value. Any illegal characters return high bit set. */ + +static unsigned char asctobin[] = { + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0076,0200,0200,0200,0077, + 0064,0065,0066,0067,0070,0071,0072,0073, + 0074,0075,0200,0200,0200,0200,0200,0200, + 0200,0000,0001,0002,0003,0004,0005,0006, + 0007,0010,0011,0012,0013,0014,0015,0016, + 0017,0020,0021,0022,0023,0024,0025,0026, + 0027,0030,0031,0200,0200,0200,0200,0200, + 0200,0032,0033,0034,0035,0036,0037,0040, + 0041,0042,0043,0044,0045,0046,0047,0050, + 0051,0052,0053,0054,0055,0056,0057,0060, + 0061,0062,0063,0200,0200,0200,0200,0200 +}; + +static void encode PROTO_LIST((unsigned char [4], unsigned char [3], int )); + +/* This will always returns 0. It is an int function for future compatibility, + done to provide compatibility with RSAREF(tm). */ + +int R_EncodePEMBlock(encodedBlock, encodedBlockLen, block, blockLen) +unsigned char *encodedBlock; /* encoded block */ +unsigned int *encodedBlockLen; /* length of encoded block */ +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +{ + unsigned int i, lastLen; + + if(blockLen < 1) { + *encodedBlockLen = 0; + return (IDOK); + } + + *encodedBlockLen = 0; + + /* Bug Fixed By SK 02/09/95 */ + for (i = 0, lastLen = blockLen; i < blockLen; i += 3) { + encode(&encodedBlock[4*i/3], &block[i], (lastLen >= 3 ? 3 : lastLen)); + lastLen -= 3; + *encodedBlockLen += 4; + } + + return(IDOK); +} + +int R_DecodePEMBlock (outbuf, outlength, inbuf, inlength) +unsigned char *outbuf; /* block */ +unsigned int *outlength; /* length of block */ +unsigned char *inbuf; /* encoded block */ +unsigned int inlength; /* length of encoded block */ +{ + unsigned char *bp; + int length; + unsigned int c1,c2,c3,c4; + register int j; + + if(inlength % 4) + return (RE_ENCODING); + + if(inlength < 1) { + *outlength = 0; + return (IDOK); + } + + + length = 0; + bp = (unsigned char *)inbuf; + + /* FOUR input characters go into each THREE output charcters */ + + while(inlength > 0) { + if(*bp&0x80 || (c1=asctobin[*bp])&0x80) + return(RE_ENCODING); + ++bp; + if(*bp&0x80 || (c2=asctobin[*bp])&0x80) + return(RE_ENCODING); + if(*++bp == PAD){ + c3 = c4 = 0; + length += 1; + if(*++bp != PAD) + return(RE_ENCODING); + } + else if(*bp&0x80 || (c3=asctobin[*bp])&0x80) + return(RE_ENCODING); + else { + if(*++bp == PAD) { + c4 = 0; + length += 2; + } + else if (*bp&0x80 || (c4=asctobin[*bp])&0x80) + return(RE_ENCODING); + else + length += 3; + } + ++bp; + j = (c1 << 2) | (c2 >> 4); + *outbuf++=j; + j = (c2 << 4) | (c3 >> 2); + *outbuf++=j; + j = (c3 << 6) | c4; + *outbuf++=j; + inlength -= 4; + } + + *outlength = length; + return(IDOK); /* normal return */ + +} + +/* + Output one group of up to 3 bytes, pointed at by p, to buffer at f. + If fewer than 3 are present, the 1 or two extras must be zeros. +*/ + +static void encode(f, p, count) +unsigned char *f; /* output buffer */ +unsigned char *p; /* input buffer */ +int count; /* count */ +{ + int c1, c2, c3, c4; + + c1 = *p >> 2; + c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017); + c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); + c4 = p[2] & 077; + *f++ = ENC(c1); + *f++ = ENC(c2); + if (count == 1) + { + *f++ = PAD; + *f++ = PAD; + }else{ + *f++ = ENC(c3); + if(count == 2) *f++ = PAD; + else *f++ = ENC(c4); + } +} + diff --git a/source/r_enhanc.c b/source/r_enhanc.c old mode 100755 new mode 100644 index 03e4d4f..d7611ff --- a/source/r_enhanc.c +++ b/source/r_enhanc.c @@ -1,930 +1,931 @@ -/* - R_ENHANC.C - cryptographic enhancements for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Cryptographic Enhancements. - - Revision history - 0.90 First revision, initial production of file. - - 0.91 Second revision, altered to incorporate the addition of - the SHS hashing algorithm to the toolkit. Waiting for OBJ ID - for SHS Signature. - - 0.92 Third revision, modified Digest, Signing and Verifying - routines with improved error checking, to prevent SHS digest - being used for signing data. R_VerifyFinal altered to check - that same digest used in original signature was used in verify - doesn't verify signature if they don't match. - - 1.02 Fourth revision, R_SealUpdate Bug fixed, Bug Reported by - Anders Heerfordt . -*/ - -#include "rsaeuro.h" -#include "r_random.h" -#include "rsa.h" - -/* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 or 4 (for MD2/MD5/MD4), - then DIGEST_INFO_B, then 16-byte message digest. */ - -/* Using the Original RSAREF/PKCS Object Indentifier, for signatures */ - -static unsigned char DIGEST_INFO_A[] = { - 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x02 -}; - -#define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A) - -static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 }; - -#define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B) - -#define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16) - -static unsigned char *PADDING[] = { - (unsigned char *)"", (unsigned char *)"\01", (unsigned char *)"\02\02", - (unsigned char *)"\03\03\03", (unsigned char *)"\04\04\04\04", - (unsigned char *)"\05\05\05\05\05", - (unsigned char *)"\06\06\06\06\06\06", - (unsigned char *)"\07\07\07\07\07\07\07", - (unsigned char *)"\08\08\08\08\08\08\08\08" -}; - -#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN - -static void R_EncodeDigestInfo PROTO_LIST((unsigned char *, int, unsigned char *)); -static int R_CheckDigestInfo PROTO_LIST ((unsigned char *, unsigned char *)); - - /* encrypt prototypes */ - -static int CipherInit PROTO_LIST((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int)); -static void EncryptBlk PROTO_LIST((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int)); -static void RestartCipher PROTO_LIST((R_ENVELOPE_CTX *)); - -int R_DigestInit(context, digesttype) -R_DIGEST_CTX *context; /* new context */ -int digesttype; /* message-digest algorithm */ -{ - context->digestAlgorithm = digesttype; - - switch(digesttype) { - case DA_SHS: - SHSInit(&context->context.shs); - break; - - case DA_MD2: - MD2Init(&context->context.md2); - break; - - case DA_MD4: - MD4Init(&context->context.md4); - break; - - case DA_MD5: - MD5Init(&context->context.md5); - break; - - default: - return(RE_DIGEST_ALGORITHM); - } - - return(IDOK); -} - -int R_DigestUpdate(context, partIn, partInLen) -R_DIGEST_CTX *context; /* context */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - switch(context->digestAlgorithm) { - case DA_SHS: - SHSUpdate(&context->context.shs, partIn, partInLen); - break; - - case DA_MD2: - MD2Update(&context->context.md2, partIn, partInLen); - break; - - case DA_MD4: - MD4Update(&context->context.md4, partIn, partInLen); - break; - - case DA_MD5: - MD5Update(&context->context.md5, partIn, partInLen); - break; - - default: - return(RE_DIGEST_ALGORITHM); - } - - return(IDOK); -} - -int R_DigestFinal(context, digest, digestLen) -R_DIGEST_CTX *context; /* context */ -unsigned char *digest; /* message digest */ -unsigned int *digestLen; /* length of message digest */ -{ - *digestLen = context->digestAlgorithm == DA_SHS ? 20 : 16; - - switch(context->digestAlgorithm) { - case DA_SHS: - SHSFinal(&context->context.shs); /* doesn't output as chars */ - break; - - case DA_MD2: - MD2Final(digest, &context->context.md2); - break; - - case DA_MD4: - MD4Final(digest, &context->context.md4); - break; - - case DA_MD5: - MD5Final(digest, &context->context.md5); - break; - - default: - return(RE_DIGEST_ALGORITHM); - } - - return(IDOK); -} - -/* Signing a file using SHS is not allowed for now */ - -int R_SignInit(context, digesttype) -R_SIGNATURE_CTX *context; /* new context */ -int digesttype; /* message-digest algorithm */ -{ - return((digesttype == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digesttype)); -} - -int R_SignUpdate(context, partIn, partInLen) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); -} - -int R_SignFinal(context, signature, signatureLen, privateKey) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *signature; /* signature */ -unsigned int *signatureLen; /* length of signature */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -{ - int status; - unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN]; - unsigned int digestLen; - - if(context->digestContext.digestAlgorithm == DA_SHS) - status = RE_DIGEST_ALGORITHM; - else { - if((status = R_DigestFinal(&context->digestContext, digest, &digestLen)) == 0) { - R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); - - if(RSAPrivateEncrypt(signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey) != 0) { - status = RE_PRIVATE_KEY; - }else{ - /* Reset for another verification. */ - R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); - } - } - /* Clear sensitive information. */ - R_memset(digest, 0, sizeof(digest)); - R_memset(digestInfo, 0, sizeof(digestInfo)); - } - - return(status); -} - -int R_VerifyInit(context, digestAlgorithm) -R_SIGNATURE_CTX *context; /* new context */ -int digestAlgorithm; /* message-digest algorithm */ -{ - return((digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digestAlgorithm)); -} - -int R_VerifyUpdate(context, partIn, partInLen) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); -} - -int R_VerifyFinal(context, signature, signatureLen, publicKey) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *signature; /* signature */ -unsigned int signatureLen; /* length of signature */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - int status; - unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN], - originalDigestInfo[MAX_SIGNATURE_LEN]; - unsigned int originalDigestInfoLen, digestLen; - - status = 0; - if(signatureLen > MAX_SIGNATURE_LEN) - status = RE_LEN; - - if(context->digestContext.digestAlgorithm == DA_SHS) - status = RE_DIGEST_ALGORITHM; - - if(!status) { - if((status = R_DigestFinal (&context->digestContext, digest, &digestLen)) == 0) { - R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); - - if(RSAPublicDecrypt(originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, publicKey) != 0) { - status = RE_PUBLIC_KEY; - }else{ /* Check the digest out */ - if((originalDigestInfoLen != DIGEST_INFO_LEN) || R_CheckDigestInfo(originalDigestInfo, digestInfo) || (R_memcmp((POINTER)originalDigestInfo, (POINTER)digestInfo, DIGEST_INFO_LEN))) - status = RE_SIGNATURE; - else - /* Reset for another verification. */ - R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); - } - } - - /* Clear sensitive information. */ - R_memset(digest, 0, sizeof(digest)); - R_memset(digestInfo, 0, sizeof(digestInfo)); - R_memset(originalDigestInfo, 0, sizeof(originalDigestInfo)); - } - - return(status); -} - -/* Caller must ASCII encode the encrypted keys if required. */ - -int R_SealInit(context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys, - encryptionAlgorithm, randomStruct) -R_ENVELOPE_CTX *context; /* new context */ -unsigned char **encryptedKeys; /* encrypted keys */ -unsigned int *encryptedKeyLens; /* lengths of encrypted keys */ -unsigned char iv[8]; /* initialization vector */ -unsigned int publicKeyCount; /* number of public keys */ -R_RSA_PUBLIC_KEY **publicKeys; /* public keys */ -int encryptionAlgorithm; /* data encryption algorithm */ -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - int status; - unsigned char key[24]; - unsigned int keyLen, i; - - context->encryptionAlgorithm = encryptionAlgorithm; - - keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24; - - if((status = R_GenerateBytes (key, keyLen, randomStruct)) == 0) { - if((status = R_GenerateBytes (iv, 8, randomStruct)) == 0) { - if(encryptionAlgorithm == EA_DES_EDE2_CBC) - /* Make both E keys the same */ - R_memcpy ((POINTER)(key + 16), (POINTER)key, 8); - - if((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) == 0) { - for(i = 0; i < publicKeyCount; ++i) { - if(RSAPublicEncrypt(encryptedKeys[i], &encryptedKeyLens[i], key, keyLen, - publicKeys[i], randomStruct)) { - status = RE_PUBLIC_KEY; - break; - } - } - } - if(status == 0) - context->bufferLen = 0; - } - } - - /* Clear sensitive information. */ - - R_memset(key, 0, sizeof(key)); - - return(status); -} - -/* partOut buffer should be at least partInLen + 7 */ - -int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* next encrypted data part */ -unsigned int *partOutLen; /* length of next encrypted data part */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - unsigned int temp; - - temp = 8 - context->bufferLen; - if(partInLen < temp) { - /* Just accumulate into buffer. */ - *partOutLen = 0; - R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, partInLen); - context->bufferLen += partInLen; /* Bug Fix - 02/09/95, SK */ - return(IDOK); - } - - /* Fill the buffer and encrypt. */ - - R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, temp); - EncryptBlk(context, partOut, context->buffer, 8); - partOut += 8; - *partOutLen = 8; - partIn += temp; - partInLen -= temp; - - /* Encrypt as many 8-byte blocks as possible. */ - - temp = 8 * (partInLen / 8); - EncryptBlk(context, partOut, partIn, temp); - *partOutLen += temp; - partIn += temp; - partInLen -= temp; - - - /* Length now less than 8, so copy remainder to buffer for next time. */ - R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); - - return(IDOK); -} - -/* Assume partOut buffer is at least 8 bytes. */ - -int R_SealFinal(context, partOut, partOutLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* last encrypted data part */ -unsigned int *partOutLen; /* length of last encrypted data part */ -{ - unsigned int padLen; - - /* Pad and encrypt final block. */ - - padLen = 8 - context->bufferLen; /* little trick to pad the block */ - R_memset((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen); - EncryptBlk(context, partOut, context->buffer, 8); - *partOutLen = 8; - - /* Restart the context. */ - - RestartCipher(context); - context->bufferLen = 0; - - return(IDOK); -} - -/* Assume caller has already ASCII decoded the encryptedKey if necessary. */ - -int R_OpenInit(context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey) -R_ENVELOPE_CTX *context; /* new context */ -int encryptionAlgorithm; /* data encryption algorithm */ -unsigned char *encryptedKey; /* encrypted data encryption key */ -unsigned int encryptedKeyLen; /* length of encrypted key */ -unsigned char iv[8]; /* initialization vector */ -R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ -{ - int status; - unsigned char key[MAX_ENCRYPTED_KEY_LEN]; - unsigned int keyLen; - - if(encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN) - return(RE_LEN); - - context->encryptionAlgorithm = encryptionAlgorithm; - - if(RSAPrivateDecrypt(key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) { - status = RE_PRIVATE_KEY; - }else{ - if(encryptionAlgorithm == EA_DES_CBC) { - if(keyLen != 8) status = RE_PRIVATE_KEY; - else{ - if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) - context->bufferLen = 0; - } - }else{ - if(keyLen != 24) status = RE_PRIVATE_KEY; - else { - if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) - context->bufferLen = 0; - } - } - } - - /* Clear sensitive information. */ - - R_memset(key, 0, sizeof(key)); - - return(status); -} - -/* Assume partOut buffer is at least partInLen + 7. - Always leaves at least one byte in buffer. */ - -int R_OpenUpdate(context, partOut, partOutLen, partIn, partInLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* next recovered data part */ -unsigned int *partOutLen; /* length of next recovered data part */ -unsigned char *partIn; /* next encrypted data part */ -unsigned int partInLen; /* length of next encrypted data part */ -{ - unsigned int tempLen; - - tempLen = 8 - context->bufferLen; - if (partInLen <= tempLen) { - /* Just accumulate into buffer. */ - *partOutLen = 0; - R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, partInLen); - context->bufferLen += partInLen; - return(IDOK); - } - - /* Fill the buffer and decrypt. We know that there will be more left - in partIn after decrypting the buffer. */ - - R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, tempLen); - - EncryptBlk (context, partOut, context->buffer, 8); - partOut += 8; - *partOutLen = 8; - partIn += tempLen; - partInLen -= tempLen; - - /* Decrypt as many 8 byte blocks as possible, leaving at least one byte - in partIn. */ - - tempLen = 8 * ((partInLen - 1) / 8); - EncryptBlk (context, partOut, partIn, tempLen); - partIn += tempLen; - *partOutLen += tempLen; - partInLen -= tempLen; - - /* Length is between 1 and 8, so copy into buffer. */ - - R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); - - return (IDOK); -} - -/* Assume partOut buffer is at least 7 bytes. */ - -int R_OpenFinal(context, partOut, partOutLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* last recovered data part */ -unsigned int *partOutLen; /* length of last recovered data part */ -{ - int status; - unsigned char lastPart[8]; - unsigned int padLen; - - status = 0; - - if(context->bufferLen == 0) - /* There was no input data to decrypt */ - *partOutLen = 0; - else { - if(context->bufferLen != 8) { - status = RE_KEY; - }else{ - - /* Decrypt and strip any padding from the final block. */ - - EncryptBlk (context, lastPart, context->buffer, 8); - - padLen = lastPart[7]; - - if(padLen == 0 || padLen > 8) - status = RE_KEY; - else{ - if(R_memcmp((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) - status = RE_KEY; - else - R_memcpy (partOut, lastPart, *partOutLen = 8 - padLen); - } - /* Restart the context. */ - if(status == 0) { - RestartCipher(context); - context->bufferLen = 0; - } - } - } - - /* Clear sensitive information. */ - - R_memset(lastPart, 0, sizeof(lastPart)); - - return (status); -} - -/**/ - -int R_SignPEMBlock(encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, - content, contentLen, recode, digestAlgorithm, privateKey) -unsigned char *encodedContent; /* encoded content */ -unsigned int *encodedContentLen; /* length of encoded content */ -unsigned char *encodedSignature; /* encoded signature */ -unsigned int *encodedSignatureLen; /* length of encoded signature */ -unsigned char *content; /* content */ -unsigned int contentLen; /* length of content */ -int recode; /* recoding flag */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -{ - int status; - unsigned char signature[MAX_SIGNATURE_LEN]; - unsigned int signatureLen; - - if((status = R_SignBlock(signature, &signatureLen, content, contentLen, digestAlgorithm, privateKey)) != 0) - return(status); - - if(recode) - R_EncodePEMBlock(encodedContent, encodedContentLen, content, contentLen); - - R_EncodePEMBlock(encodedSignature, encodedSignatureLen, signature, signatureLen); - - return(IDOK); -} - -int R_SignBlock(signature, signatureLen, block, blockLen, digestAlgorithm, privateKey) -unsigned char *signature; /* signature */ -unsigned int *signatureLen; /* length of signature */ -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -{ - R_SIGNATURE_CTX context; - int status; - - if((status = R_SignInit(&context, digestAlgorithm)) == 0) - if((status = R_SignUpdate(&context, block, blockLen)) == 0) - status = R_SignFinal(&context, signature, signatureLen, privateKey); - - /* Clear sensitive information. */ - R_memset((POINTER)&context, 0, sizeof(context)); - - return(status); -} - -int R_VerifyPEMSignature(content, contentLen, encodedContent, encodedContentLen, encodedSignature, - encodedSignatureLen, recode, digestAlgorithm, publicKey) -unsigned char *content; /* content */ -unsigned int *contentLen; /* length of content */ -unsigned char *encodedContent; /* (possibly) encoded content */ -unsigned int encodedContentLen; /* length of encoded content */ -unsigned char *encodedSignature; /* encoded signature */ -unsigned int encodedSignatureLen; /* length of encoded signature */ -int recode; /* recoding flag */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - unsigned char signature[MAX_SIGNATURE_LEN]; - unsigned int signatureLen; - - if(encodedSignatureLen > MAX_PEM_SIGNATURE_LEN) - return(RE_SIGNATURE_ENCODING); - - if(recode) { - if(R_DecodePEMBlock(content, contentLen, encodedContent, encodedContentLen)) - return(RE_CONTENT_ENCODING); - }else{ - *contentLen = encodedContentLen; - content = encodedContent; - } - - if(R_DecodePEMBlock(signature, &signatureLen, encodedSignature, encodedSignatureLen)) - return (RE_SIGNATURE_ENCODING); - - return(R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey)); -} - -int R_VerifyBlockSignature(block, blockLen, signature, signatureLen, digestAlgorithm, publicKey) -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -unsigned char *signature; /* signature */ -unsigned int signatureLen; /* length of signature */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - R_SIGNATURE_CTX context; - int status; - - if((status = R_VerifyInit(&context, digestAlgorithm)) == 0) - if((status = R_VerifyUpdate(&context, block, blockLen)) == 0) - status = R_VerifyFinal(&context, signature, signatureLen, publicKey); - - /* Clear sensitive information. */ - R_memset((POINTER)&context, 0, sizeof(context)); - - return(status); -} - -int R_SealPEMBlock(encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, - encryptedSignature, encryptedSignatureLen, iv, content, contentLen, - digestAlgorithm, publicKey, privateKey, randomStruct) -unsigned char *encryptedContent; /* encoded, encrypted content */ -unsigned int *encryptedContentLen; /* length */ -unsigned char *encryptedKey; /* encoded, encrypted key */ -unsigned int *encryptedKeyLen; /* length */ -unsigned char *encryptedSignature; /* encoded, encrypted signature */ -unsigned int *encryptedSignatureLen; /* length */ -unsigned char iv[8]; /* DES initialization vector */ -unsigned char *content; /* content */ -unsigned int contentLen; /* length of content */ -int digestAlgorithm; /* message-digest algorithms */ -R_RSA_PUBLIC_KEY *publicKey; /* recipient's RSA public key */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - R_ENVELOPE_CTX context; - R_RSA_PUBLIC_KEY *publicKeys[1]; - int status; - unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], - signature[MAX_SIGNATURE_LEN], *encryptedKeys[1]; - unsigned int signatureLen, encryptedKeyBlockLen; - - if((status = R_SignBlock(signature, &signatureLen, content, contentLen, - digestAlgorithm, privateKey)) == 0) { - - encryptedKeys[0] = encryptedKeyBlock; - publicKeys[0] = publicKey; - - if((status = R_SealInit(&context, encryptedKeys, &encryptedKeyBlockLen, iv, 1, publicKeys, EA_DES_CBC, randomStruct)) == 0) { - - R_EncodePEMBlock(encryptedKey, encryptedKeyLen, encryptedKeyBlock, - encryptedKeyBlockLen); - - R_EncryptOpenPEMBlock(&context, encryptedContent, encryptedContentLen, - content, contentLen); - - R_EncryptOpenPEMBlock(&context, encryptedSignature, encryptedSignatureLen, - signature, signatureLen); - } - } - - /* Clear sensitive information. */ - R_memset((POINTER)&context, 0, sizeof(context)); - R_memset(signature, 0, sizeof(signature)); - - return (status); -} - -int R_OpenPEMBlock(content, contentLen, encryptedContent, encryptedContentLen, encryptedKey, - encryptedKeyLen, encryptedSignature, encryptedSignatureLen, - iv, digestAlgorithm, privateKey, publicKey) -unsigned char *content; /* content */ -unsigned int *contentLen; /* length of content */ -unsigned char *encryptedContent; /* encoded, encrypted content */ -unsigned int encryptedContentLen; /* length */ -unsigned char *encryptedKey; /* encoded, encrypted key */ -unsigned int encryptedKeyLen; /* length */ -unsigned char *encryptedSignature; /* encoded, encrypted signature */ -unsigned int encryptedSignatureLen; /* length */ -unsigned char iv[8]; /* DES initialization vector */ -int digestAlgorithm; /* message-digest algorithms */ -R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - R_ENVELOPE_CTX context; - int status; - unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], - signature[MAX_SIGNATURE_LEN]; - unsigned int encryptedKeyBlockLen, signatureLen; - - if(encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN) - return(RE_SIGNATURE_ENCODING); - - if(encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN) - return(RE_KEY_ENCODING); - - if(R_DecodePEMBlock(encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey, encryptedKeyLen) != 0) { - status = RE_KEY_ENCODING; - }else{ - if((status = R_OpenInit(&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen, iv, privateKey)) == 0) { - - if((status = R_DecryptOpenPEMBlock(&context, content, contentLen, encryptedContent, encryptedContentLen)) != 0) { - if((status == RE_LEN || status == RE_ENCODING)) - status = RE_CONTENT_ENCODING; - else - status = RE_KEY; - }else{ - - status = R_DecryptOpenPEMBlock(&context, signature, &signatureLen, encryptedSignature, encryptedSignatureLen); - - if(status) { - if((status == RE_LEN || status == RE_ENCODING)) - status = RE_SIGNATURE_ENCODING; - else - status = RE_KEY; - }else - status = R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey); - } - } - } - /* Clear sensitive information. */ - - R_memset((POINTER)&context, 0, sizeof(context)); - R_memset(signature, 0, sizeof(signature)); - - return(status); -} - -int R_DigestBlock(digest, digestLen, block, blockLen, digestAlgorithm) -unsigned char *digest; /* message digest */ -unsigned int *digestLen; /* length of message digest */ -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -int digestAlgorithm; /* message-digest algorithm */ -{ - R_DIGEST_CTX context; - int status; - - if((status = R_DigestInit(&context, digestAlgorithm)) == 0) - if((status = R_DigestUpdate(&context, block, blockLen)) == 0) - status = R_DigestFinal(&context, digest, digestLen); - - /* Clear sensitive information. */ - - R_memset((POINTER)&context, 0, sizeof(context)); - - return(status); -} - -int R_DecryptOpenPEMBlock(context, output, outputLen, input, inputLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *output; /* decoded, decrypted block */ -unsigned int *outputLen; /* length of output */ -unsigned char *input; /* encrypted, encoded block */ -unsigned int inputLen; /* length */ -{ - int status; - unsigned char encryptedPart[24]; - unsigned int i, len; - - *outputLen = 0; - - for (i = 0; i < inputLen/32; i++) { - /* len is always 24 */ - if ((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], 32)) != 0) - break; - - R_OpenUpdate (context, output, &len, encryptedPart, 24); - *outputLen += len; - output += len; - } - - if(!status) /* Decode the last block. */ - if((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], inputLen - 32*i)) == 0) { - /* Decrypt the last block. */ - R_OpenUpdate (context, output, &len, encryptedPart, len); - output += len; - *outputLen += len; - if((status = R_OpenFinal (context, output, &len)) == 0) - *outputLen += len; - } - - /* Clear sensitive information. */ - - R_memset((POINTER)&context, 0, sizeof(context)); - R_memset(encryptedPart, 0, sizeof(encryptedPart)); - - return(status); -} - -int R_EncryptOpenPEMBlock(context, output, outputLen, input, inputLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *output; /* encrypted, encoded block */ -unsigned int *outputLen; /* length of output */ -unsigned char *input; /* block to encrypt */ -unsigned int inputLen; /* length */ -{ - unsigned char encryptedPart[24]; - unsigned int i, lastPartLen, tempLen, len; - - /* Encrypt and encode as many 24-byte blocks as possible. */ - - for (i = 0; i < inputLen / 24; ++i) { - /* Assume part out length will equal part in length since it is - a multiple of 8. Also assume no error output. */ - R_SealUpdate (context, encryptedPart, &tempLen, &input[24*i], 24); - - /* len will always be 32 */ - R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24); - } - - /* Encrypt the last part into encryptedPart. */ - - R_SealUpdate(context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i); - R_SealFinal(context, encryptedPart + lastPartLen, &len); - lastPartLen += len; - - R_EncodePEMBlock(&output[32*i], &len, encryptedPart, lastPartLen); - *outputLen = 32*i + len; - - /* Clear sensitive information. */ - - R_memset(encryptedPart, 0, sizeof(encryptedPart)); - - return(IDOK); -} - -/* Assumes that digestAlgorithm is DA_MD2, DA_MD4 or DA_MD5 and - the digest length must be 16. SHS Not supported here. */ - -static void R_EncodeDigestInfo(digestInfo, digestAlgorithm, digest) -unsigned char *digestInfo; -int digestAlgorithm; -unsigned char *digest; -{ - if(!(digestAlgorithm == DA_SHS)) { - digestInfo[DIGEST_INFO_A_LEN] = digestAlgorithm; - - R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B, DIGEST_INFO_B_LEN); - R_memcpy((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN); - R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN], (POINTER)digest, 16); - } -} - -/* Quick check to correct digest was used to verify */ - -static int R_CheckDigestInfo(originaldigestInfo, digestInfo) -unsigned char *originaldigestInfo; -unsigned char *digestInfo; -{ - return((originaldigestInfo[DIGEST_INFO_A_LEN] == - digestInfo[DIGEST_INFO_A_LEN]) ? IDOK : RE_SIGNATURE); -} - -static int CipherInit(context, encryptionAlgorithm, key, iv, encrypt) -R_ENVELOPE_CTX *context; -int encryptionAlgorithm; -unsigned char *key; -unsigned char *iv; -int encrypt; -{ - switch(encryptionAlgorithm) { - case EA_DES_CBC: - DES_CBCInit (&context->cipherContext.des, key, iv, encrypt); - break; - case EA_DESX_CBC: - DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt); - break; - case EA_DES_EDE2_CBC: - case EA_DES_EDE3_CBC: - DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt); - break; - default: - return (RE_ENCRYPTION_ALGORITHM); - } - return(IDOK); -} - -/* Assume len is a multiple of 8. - */ -static void EncryptBlk(context, output, input, len) -R_ENVELOPE_CTX *context; -unsigned char *output; -unsigned char *input; -unsigned int len; -{ - switch(context->encryptionAlgorithm) { - case EA_DES_CBC: - DES_CBCUpdate (&context->cipherContext.des, output, input, len); - break; - case EA_DESX_CBC: - DESX_CBCUpdate (&context->cipherContext.desx, output, input, len); - break; - case EA_DES_EDE2_CBC: - case EA_DES_EDE3_CBC: - DES3_CBCUpdate (&context->cipherContext.des3, output, input, len); - } -} - -static void RestartCipher(context) -R_ENVELOPE_CTX *context; -{ - switch(context->encryptionAlgorithm) { - case EA_DES_CBC: - DES_CBCRestart (&context->cipherContext.des); - break; - case EA_DESX_CBC: - DESX_CBCRestart (&context->cipherContext.desx); - break; - case EA_DES_EDE2_CBC: - case EA_DES_EDE3_CBC: - DES3_CBCRestart (&context->cipherContext.des3); - } -} +/* + R_ENHANC.C - cryptographic enhancements for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Cryptographic Enhancements. + + Revision history + 0.90 First revision, initial production of file. + + 0.91 Second revision, altered to incorporate the addition of + the SHS hashing algorithm to the toolkit. Waiting for OBJ ID + for SHS Signature. + + 0.92 Third revision, modified Digest, Signing and Verifying + routines with improved error checking, to prevent SHS digest + being used for signing data. R_VerifyFinal altered to check + that same digest used in original signature was used in verify + doesn't verify signature if they don't match. + + 1.02 Fourth revision, R_SealUpdate Bug fixed, Bug Reported by + Anders Heerfordt . PADDING problem array incorrectly + setup, reported by Anders Heerfordt . +*/ + +#include "rsaeuro.h" +#include "r_random.h" +#include "rsa.h" + +/* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 or 4 (for MD2/MD5/MD4), + then DIGEST_INFO_B, then 16-byte message digest. */ + +/* Using the Original RSAREF/PKCS Object Indentifier, for signatures */ + +static unsigned char DIGEST_INFO_A[] = { + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x02 +}; + +#define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A) + +static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 }; + +#define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B) + +#define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16) + +static unsigned char *PADDING[] = { + (unsigned char *)"", (unsigned char *)"\01", (unsigned char *)"\02\02", + (unsigned char *)"\03\03\03", (unsigned char *)"\04\04\04\04", + (unsigned char *)"\05\05\05\05\05", + (unsigned char *)"\06\06\06\06\06\06", + (unsigned char *)"\07\07\07\07\07\07\07", + (unsigned char *)"\08\08\08\08\08\08\08\08" +}; + +#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN + +static void R_EncodeDigestInfo PROTO_LIST((unsigned char *, int, unsigned char *)); +static int R_CheckDigestInfo PROTO_LIST ((unsigned char *, unsigned char *)); + + /* encrypt prototypes */ + +static int CipherInit PROTO_LIST((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int)); +static void EncryptBlk PROTO_LIST((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int)); +static void RestartCipher PROTO_LIST((R_ENVELOPE_CTX *)); + +int R_DigestInit(context, digesttype) +R_DIGEST_CTX *context; /* new context */ +int digesttype; /* message-digest algorithm */ +{ + context->digestAlgorithm = digesttype; + + switch(digesttype) { + case DA_SHS: + SHSInit(&context->context.shs); + break; + + case DA_MD2: + MD2Init(&context->context.md2); + break; + + case DA_MD4: + MD4Init(&context->context.md4); + break; + + case DA_MD5: + MD5Init(&context->context.md5); + break; + + default: + return(RE_DIGEST_ALGORITHM); + } + + return(IDOK); +} + +int R_DigestUpdate(context, partIn, partInLen) +R_DIGEST_CTX *context; /* context */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + switch(context->digestAlgorithm) { + case DA_SHS: + SHSUpdate(&context->context.shs, partIn, partInLen); + break; + + case DA_MD2: + MD2Update(&context->context.md2, partIn, partInLen); + break; + + case DA_MD4: + MD4Update(&context->context.md4, partIn, partInLen); + break; + + case DA_MD5: + MD5Update(&context->context.md5, partIn, partInLen); + break; + + default: + return(RE_DIGEST_ALGORITHM); + } + + return(IDOK); +} + +int R_DigestFinal(context, digest, digestLen) +R_DIGEST_CTX *context; /* context */ +unsigned char *digest; /* message digest */ +unsigned int *digestLen; /* length of message digest */ +{ + *digestLen = context->digestAlgorithm == DA_SHS ? 20 : 16; + + switch(context->digestAlgorithm) { + case DA_SHS: + SHSFinal(digest, &context->context.shs); /* doesn't output as chars */ + break; + + case DA_MD2: + MD2Final(digest, &context->context.md2); + break; + + case DA_MD4: + MD4Final(digest, &context->context.md4); + break; + + case DA_MD5: + MD5Final(digest, &context->context.md5); + break; + + default: + return(RE_DIGEST_ALGORITHM); + } + + return(IDOK); +} + +/* Signing a file using SHS is not allowed for now */ + +int R_SignInit(context, digesttype) +R_SIGNATURE_CTX *context; /* new context */ +int digesttype; /* message-digest algorithm */ +{ + return((digesttype == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digesttype)); +} + +int R_SignUpdate(context, partIn, partInLen) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); +} + +int R_SignFinal(context, signature, signatureLen, privateKey) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *signature; /* signature */ +unsigned int *signatureLen; /* length of signature */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +{ + int status; + unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN]; + unsigned int digestLen; + + if(context->digestContext.digestAlgorithm == DA_SHS) + status = RE_DIGEST_ALGORITHM; + else { + if((status = R_DigestFinal(&context->digestContext, digest, &digestLen)) == 0) { + R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); + + if(RSAPrivateEncrypt(signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey) != 0) { + status = RE_PRIVATE_KEY; + }else{ + /* Reset for another verification. */ + R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); + } + } + /* Clear sensitive information. */ + R_memset(digest, 0, sizeof(digest)); + R_memset(digestInfo, 0, sizeof(digestInfo)); + } + + return(status); +} + +int R_VerifyInit(context, digestAlgorithm) +R_SIGNATURE_CTX *context; /* new context */ +int digestAlgorithm; /* message-digest algorithm */ +{ + return((digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digestAlgorithm)); +} + +int R_VerifyUpdate(context, partIn, partInLen) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); +} + +int R_VerifyFinal(context, signature, signatureLen, publicKey) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *signature; /* signature */ +unsigned int signatureLen; /* length of signature */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + int status; + unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN], + originalDigestInfo[MAX_SIGNATURE_LEN]; + unsigned int originalDigestInfoLen, digestLen; + + status = 0; + if(signatureLen > MAX_SIGNATURE_LEN) + status = RE_LEN; + + if(context->digestContext.digestAlgorithm == DA_SHS) + status = RE_DIGEST_ALGORITHM; + + if(!status) { + if((status = R_DigestFinal (&context->digestContext, digest, &digestLen)) == 0) { + R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); + + if(RSAPublicDecrypt(originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, publicKey) != 0) { + status = RE_PUBLIC_KEY; + }else{ /* Check the digest out */ + if((originalDigestInfoLen != DIGEST_INFO_LEN) || R_CheckDigestInfo(originalDigestInfo, digestInfo) || (R_memcmp((POINTER)originalDigestInfo, (POINTER)digestInfo, DIGEST_INFO_LEN))) + status = RE_SIGNATURE; + else + /* Reset for another verification. */ + R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); + } + } + + /* Clear sensitive information. */ + R_memset(digest, 0, sizeof(digest)); + R_memset(digestInfo, 0, sizeof(digestInfo)); + R_memset(originalDigestInfo, 0, sizeof(originalDigestInfo)); + } + + return(status); +} + +/* Caller must ASCII encode the encrypted keys if required. */ + +int R_SealInit(context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys, + encryptionAlgorithm, randomStruct) +R_ENVELOPE_CTX *context; /* new context */ +unsigned char **encryptedKeys; /* encrypted keys */ +unsigned int *encryptedKeyLens; /* lengths of encrypted keys */ +unsigned char iv[8]; /* initialization vector */ +unsigned int publicKeyCount; /* number of public keys */ +R_RSA_PUBLIC_KEY **publicKeys; /* public keys */ +int encryptionAlgorithm; /* data encryption algorithm */ +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + int status; + unsigned char key[24]; + unsigned int keyLen, i; + + context->encryptionAlgorithm = encryptionAlgorithm; + + keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24; + + if((status = R_GenerateBytes (key, keyLen, randomStruct)) == 0) { + if((status = R_GenerateBytes (iv, 8, randomStruct)) == 0) { + if(encryptionAlgorithm == EA_DES_EDE2_CBC) + /* Make both E keys the same */ + R_memcpy ((POINTER)(key + 16), (POINTER)key, 8); + + if((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) == 0) { + for(i = 0; i < publicKeyCount; ++i) { + if(RSAPublicEncrypt(encryptedKeys[i], &encryptedKeyLens[i], key, keyLen, + publicKeys[i], randomStruct)) { + status = RE_PUBLIC_KEY; + break; + } + } + } + if(status == 0) + context->bufferLen = 0; + } + } + + /* Clear sensitive information. */ + + R_memset(key, 0, sizeof(key)); + + return(status); +} + +/* partOut buffer should be at least partInLen + 7 */ + +int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* next encrypted data part */ +unsigned int *partOutLen; /* length of next encrypted data part */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + unsigned int temp; + + temp = 8 - context->bufferLen; + if(partInLen < temp) { + /* Just accumulate into buffer. */ + *partOutLen = 0; + R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, partInLen); + context->bufferLen += partInLen; /* Bug Fix - 02/09/95, SK */ + return(IDOK); + } + + /* Fill the buffer and encrypt. */ + + R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, temp); + EncryptBlk(context, partOut, context->buffer, 8); + partOut += 8; + *partOutLen = 8; + partIn += temp; + partInLen -= temp; + + /* Encrypt as many 8-byte blocks as possible. */ + + temp = 8 * (partInLen / 8); + EncryptBlk(context, partOut, partIn, temp); + *partOutLen += temp; + partIn += temp; + partInLen -= temp; + + + /* Length now less than 8, so copy remainder to buffer for next time. */ + R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); + + return(IDOK); +} + +/* Assume partOut buffer is at least 8 bytes. */ + +int R_SealFinal(context, partOut, partOutLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* last encrypted data part */ +unsigned int *partOutLen; /* length of last encrypted data part */ +{ + unsigned int padLen; + + /* Pad and encrypt final block. */ + + padLen = 8 - context->bufferLen; /* little trick to pad the block */ + R_memset((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen); + EncryptBlk(context, partOut, context->buffer, 8); + *partOutLen = 8; + + /* Restart the context. */ + + RestartCipher(context); + context->bufferLen = 0; + + return(IDOK); +} + +/* Assume caller has already ASCII decoded the encryptedKey if necessary. */ + +int R_OpenInit(context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey) +R_ENVELOPE_CTX *context; /* new context */ +int encryptionAlgorithm; /* data encryption algorithm */ +unsigned char *encryptedKey; /* encrypted data encryption key */ +unsigned int encryptedKeyLen; /* length of encrypted key */ +unsigned char iv[8]; /* initialization vector */ +R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ +{ + int status; + unsigned char key[MAX_ENCRYPTED_KEY_LEN]; + unsigned int keyLen; + + if(encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN) + return(RE_LEN); + + context->encryptionAlgorithm = encryptionAlgorithm; + + if(RSAPrivateDecrypt(key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) { + status = RE_PRIVATE_KEY; + }else{ + if(encryptionAlgorithm == EA_DES_CBC) { + if(keyLen != 8) status = RE_PRIVATE_KEY; + else{ + if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) + context->bufferLen = 0; + } + }else{ + if(keyLen != 24) status = RE_PRIVATE_KEY; + else { + if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) + context->bufferLen = 0; + } + } + } + + /* Clear sensitive information. */ + + R_memset(key, 0, sizeof(key)); + + return(status); +} + +/* Assume partOut buffer is at least partInLen + 7. + Always leaves at least one byte in buffer. */ + +int R_OpenUpdate(context, partOut, partOutLen, partIn, partInLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* next recovered data part */ +unsigned int *partOutLen; /* length of next recovered data part */ +unsigned char *partIn; /* next encrypted data part */ +unsigned int partInLen; /* length of next encrypted data part */ +{ + unsigned int tempLen; + + tempLen = 8 - context->bufferLen; + if (partInLen <= tempLen) { + /* Just accumulate into buffer. */ + *partOutLen = 0; + R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, partInLen); + context->bufferLen += partInLen; + return(IDOK); + } + + /* Fill the buffer and decrypt. We know that there will be more left + in partIn after decrypting the buffer. */ + + R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, tempLen); + + EncryptBlk (context, partOut, context->buffer, 8); + partOut += 8; + *partOutLen = 8; + partIn += tempLen; + partInLen -= tempLen; + + /* Decrypt as many 8 byte blocks as possible, leaving at least one byte + in partIn. */ + + tempLen = 8 * ((partInLen - 1) / 8); + EncryptBlk (context, partOut, partIn, tempLen); + partIn += tempLen; + *partOutLen += tempLen; + partInLen -= tempLen; + + /* Length is between 1 and 8, so copy into buffer. */ + + R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); + + return (IDOK); +} + +/* Assume partOut buffer is at least 7 bytes. */ + +int R_OpenFinal(context, partOut, partOutLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* last recovered data part */ +unsigned int *partOutLen; /* length of last recovered data part */ +{ + int status; + unsigned char lastPart[8]; + unsigned int padLen; + + status = 0; + + if(context->bufferLen == 0) + /* There was no input data to decrypt */ + *partOutLen = 0; + else { + if(context->bufferLen != 8) { + status = RE_KEY; + }else{ + + /* Decrypt and strip any padding from the final block. */ + + EncryptBlk (context, lastPart, context->buffer, 8); + + padLen = lastPart[7]; + + if(padLen == 0 || padLen > 8) + status = RE_KEY; + else{ + if(R_memcmp((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) + status = RE_KEY; + else + R_memcpy (partOut, lastPart, *partOutLen = 8 - padLen); + } + /* Restart the context. */ + if(status == 0) { + RestartCipher(context); + context->bufferLen = 0; + } + } + } + + /* Clear sensitive information. */ + + R_memset(lastPart, 0, sizeof(lastPart)); + + return (status); +} + +/**/ + +int R_SignPEMBlock(encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, + content, contentLen, recode, digestAlgorithm, privateKey) +unsigned char *encodedContent; /* encoded content */ +unsigned int *encodedContentLen; /* length of encoded content */ +unsigned char *encodedSignature; /* encoded signature */ +unsigned int *encodedSignatureLen; /* length of encoded signature */ +unsigned char *content; /* content */ +unsigned int contentLen; /* length of content */ +int recode; /* recoding flag */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +{ + int status; + unsigned char signature[MAX_SIGNATURE_LEN]; + unsigned int signatureLen; + + if((status = R_SignBlock(signature, &signatureLen, content, contentLen, digestAlgorithm, privateKey)) != 0) + return(status); + + if(recode) + R_EncodePEMBlock(encodedContent, encodedContentLen, content, contentLen); + + R_EncodePEMBlock(encodedSignature, encodedSignatureLen, signature, signatureLen); + + return(IDOK); +} + +int R_SignBlock(signature, signatureLen, block, blockLen, digestAlgorithm, privateKey) +unsigned char *signature; /* signature */ +unsigned int *signatureLen; /* length of signature */ +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +{ + R_SIGNATURE_CTX context; + int status; + + if((status = R_SignInit(&context, digestAlgorithm)) == 0) + if((status = R_SignUpdate(&context, block, blockLen)) == 0) + status = R_SignFinal(&context, signature, signatureLen, privateKey); + + /* Clear sensitive information. */ + R_memset((POINTER)&context, 0, sizeof(context)); + + return(status); +} + +int R_VerifyPEMSignature(content, contentLen, encodedContent, encodedContentLen, encodedSignature, + encodedSignatureLen, recode, digestAlgorithm, publicKey) +unsigned char *content; /* content */ +unsigned int *contentLen; /* length of content */ +unsigned char *encodedContent; /* (possibly) encoded content */ +unsigned int encodedContentLen; /* length of encoded content */ +unsigned char *encodedSignature; /* encoded signature */ +unsigned int encodedSignatureLen; /* length of encoded signature */ +int recode; /* recoding flag */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + unsigned char signature[MAX_SIGNATURE_LEN]; + unsigned int signatureLen; + + if(encodedSignatureLen > MAX_PEM_SIGNATURE_LEN) + return(RE_SIGNATURE_ENCODING); + + if(recode) { + if(R_DecodePEMBlock(content, contentLen, encodedContent, encodedContentLen)) + return(RE_CONTENT_ENCODING); + }else{ + *contentLen = encodedContentLen; + content = encodedContent; + } + + if(R_DecodePEMBlock(signature, &signatureLen, encodedSignature, encodedSignatureLen)) + return (RE_SIGNATURE_ENCODING); + + return(R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey)); +} + +int R_VerifyBlockSignature(block, blockLen, signature, signatureLen, digestAlgorithm, publicKey) +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +unsigned char *signature; /* signature */ +unsigned int signatureLen; /* length of signature */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + R_SIGNATURE_CTX context; + int status; + + if((status = R_VerifyInit(&context, digestAlgorithm)) == 0) + if((status = R_VerifyUpdate(&context, block, blockLen)) == 0) + status = R_VerifyFinal(&context, signature, signatureLen, publicKey); + + /* Clear sensitive information. */ + R_memset((POINTER)&context, 0, sizeof(context)); + + return(status); +} + +int R_SealPEMBlock(encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, + encryptedSignature, encryptedSignatureLen, iv, content, contentLen, + digestAlgorithm, publicKey, privateKey, randomStruct) +unsigned char *encryptedContent; /* encoded, encrypted content */ +unsigned int *encryptedContentLen; /* length */ +unsigned char *encryptedKey; /* encoded, encrypted key */ +unsigned int *encryptedKeyLen; /* length */ +unsigned char *encryptedSignature; /* encoded, encrypted signature */ +unsigned int *encryptedSignatureLen; /* length */ +unsigned char iv[8]; /* DES initialization vector */ +unsigned char *content; /* content */ +unsigned int contentLen; /* length of content */ +int digestAlgorithm; /* message-digest algorithms */ +R_RSA_PUBLIC_KEY *publicKey; /* recipient's RSA public key */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + R_ENVELOPE_CTX context; + R_RSA_PUBLIC_KEY *publicKeys[1]; + int status; + unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], + signature[MAX_SIGNATURE_LEN], *encryptedKeys[1]; + unsigned int signatureLen, encryptedKeyBlockLen; + + if((status = R_SignBlock(signature, &signatureLen, content, contentLen, + digestAlgorithm, privateKey)) == 0) { + + encryptedKeys[0] = encryptedKeyBlock; + publicKeys[0] = publicKey; + + if((status = R_SealInit(&context, encryptedKeys, &encryptedKeyBlockLen, iv, 1, publicKeys, EA_DES_CBC, randomStruct)) == 0) { + + R_EncodePEMBlock(encryptedKey, encryptedKeyLen, encryptedKeyBlock, + encryptedKeyBlockLen); + + R_EncryptOpenPEMBlock(&context, encryptedContent, encryptedContentLen, + content, contentLen); + + R_EncryptOpenPEMBlock(&context, encryptedSignature, encryptedSignatureLen, + signature, signatureLen); + } + } + + /* Clear sensitive information. */ + R_memset((POINTER)&context, 0, sizeof(context)); + R_memset(signature, 0, sizeof(signature)); + + return (status); +} + +int R_OpenPEMBlock(content, contentLen, encryptedContent, encryptedContentLen, encryptedKey, + encryptedKeyLen, encryptedSignature, encryptedSignatureLen, + iv, digestAlgorithm, privateKey, publicKey) +unsigned char *content; /* content */ +unsigned int *contentLen; /* length of content */ +unsigned char *encryptedContent; /* encoded, encrypted content */ +unsigned int encryptedContentLen; /* length */ +unsigned char *encryptedKey; /* encoded, encrypted key */ +unsigned int encryptedKeyLen; /* length */ +unsigned char *encryptedSignature; /* encoded, encrypted signature */ +unsigned int encryptedSignatureLen; /* length */ +unsigned char iv[8]; /* DES initialization vector */ +int digestAlgorithm; /* message-digest algorithms */ +R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + R_ENVELOPE_CTX context; + int status; + unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], + signature[MAX_SIGNATURE_LEN]; + unsigned int encryptedKeyBlockLen, signatureLen; + + if(encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN) + return(RE_SIGNATURE_ENCODING); + + if(encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN) + return(RE_KEY_ENCODING); + + if(R_DecodePEMBlock(encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey, encryptedKeyLen) != 0) { + status = RE_KEY_ENCODING; + }else{ + if((status = R_OpenInit(&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen, iv, privateKey)) == 0) { + + if((status = R_DecryptOpenPEMBlock(&context, content, contentLen, encryptedContent, encryptedContentLen)) != 0) { + if((status == RE_LEN || status == RE_ENCODING)) + status = RE_CONTENT_ENCODING; + else + status = RE_KEY; + }else{ + + status = R_DecryptOpenPEMBlock(&context, signature, &signatureLen, encryptedSignature, encryptedSignatureLen); + + if(status) { + if((status == RE_LEN || status == RE_ENCODING)) + status = RE_SIGNATURE_ENCODING; + else + status = RE_KEY; + }else + status = R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey); + } + } + } + /* Clear sensitive information. */ + + R_memset((POINTER)&context, 0, sizeof(context)); + R_memset(signature, 0, sizeof(signature)); + + return(status); +} + +int R_DigestBlock(digest, digestLen, block, blockLen, digestAlgorithm) +unsigned char *digest; /* message digest */ +unsigned int *digestLen; /* length of message digest */ +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +int digestAlgorithm; /* message-digest algorithm */ +{ + R_DIGEST_CTX context; + int status; + + if((status = R_DigestInit(&context, digestAlgorithm)) == 0) + if((status = R_DigestUpdate(&context, block, blockLen)) == 0) + status = R_DigestFinal(&context, digest, digestLen); + + /* Clear sensitive information. */ + + R_memset((POINTER)&context, 0, sizeof(context)); + + return(status); +} + +int R_DecryptOpenPEMBlock(context, output, outputLen, input, inputLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *output; /* decoded, decrypted block */ +unsigned int *outputLen; /* length of output */ +unsigned char *input; /* encrypted, encoded block */ +unsigned int inputLen; /* length */ +{ + int status; + unsigned char encryptedPart[24]; + unsigned int i, len; + + *outputLen = 0; + + for (i = 0; i < inputLen/32; i++) { + /* len is always 24 */ + if ((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], 32)) != 0) + break; + + R_OpenUpdate (context, output, &len, encryptedPart, 24); + *outputLen += len; + output += len; + } + + if(!status) /* Decode the last block. */ + if((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], inputLen - 32*i)) == 0) { + /* Decrypt the last block. */ + R_OpenUpdate (context, output, &len, encryptedPart, len); + output += len; + *outputLen += len; + if((status = R_OpenFinal (context, output, &len)) == 0) + *outputLen += len; + } + + /* Clear sensitive information. */ + + R_memset((POINTER)&context, 0, sizeof(context)); + R_memset(encryptedPart, 0, sizeof(encryptedPart)); + + return(status); +} + +int R_EncryptOpenPEMBlock(context, output, outputLen, input, inputLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *output; /* encrypted, encoded block */ +unsigned int *outputLen; /* length of output */ +unsigned char *input; /* block to encrypt */ +unsigned int inputLen; /* length */ +{ + unsigned char encryptedPart[24]; + unsigned int i, lastPartLen, tempLen, len; + + /* Encrypt and encode as many 24-byte blocks as possible. */ + + for (i = 0; i < inputLen / 24; ++i) { + /* Assume part out length will equal part in length since it is + a multiple of 8. Also assume no error output. */ + R_SealUpdate (context, encryptedPart, &tempLen, &input[24*i], 24); + + /* len will always be 32 */ + R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24); + } + + /* Encrypt the last part into encryptedPart. */ + + R_SealUpdate(context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i); + R_SealFinal(context, encryptedPart + lastPartLen, &len); + lastPartLen += len; + + R_EncodePEMBlock(&output[32*i], &len, encryptedPart, lastPartLen); + *outputLen = 32*i + len; + + /* Clear sensitive information. */ + + R_memset(encryptedPart, 0, sizeof(encryptedPart)); + + return(IDOK); +} + +/* Assumes that digestAlgorithm is DA_MD2, DA_MD4 or DA_MD5 and + the digest length must be 16. SHS Not supported here. */ + +static void R_EncodeDigestInfo(digestInfo, digestAlgorithm, digest) +unsigned char *digestInfo; +int digestAlgorithm; +unsigned char *digest; +{ + if(!(digestAlgorithm == DA_SHS)) { + digestInfo[DIGEST_INFO_A_LEN] = digestAlgorithm; + + R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B, DIGEST_INFO_B_LEN); + R_memcpy((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN); + R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN], (POINTER)digest, 16); + } +} + +/* Quick check to correct digest was used to verify */ + +static int R_CheckDigestInfo(originaldigestInfo, digestInfo) +unsigned char *originaldigestInfo; +unsigned char *digestInfo; +{ + return((originaldigestInfo[DIGEST_INFO_A_LEN] == + digestInfo[DIGEST_INFO_A_LEN]) ? IDOK : RE_SIGNATURE); +} + +static int CipherInit(context, encryptionAlgorithm, key, iv, encrypt) +R_ENVELOPE_CTX *context; +int encryptionAlgorithm; +unsigned char *key; +unsigned char *iv; +int encrypt; +{ + switch(encryptionAlgorithm) { + case EA_DES_CBC: + DES_CBCInit (&context->cipherContext.des, key, iv, encrypt); + break; + case EA_DESX_CBC: + DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt); + break; + case EA_DES_EDE2_CBC: + case EA_DES_EDE3_CBC: + DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt); + break; + default: + return (RE_ENCRYPTION_ALGORITHM); + } + return(IDOK); +} + +/* Assume len is a multiple of 8. + */ +static void EncryptBlk(context, output, input, len) +R_ENVELOPE_CTX *context; +unsigned char *output; +unsigned char *input; +unsigned int len; +{ + switch(context->encryptionAlgorithm) { + case EA_DES_CBC: + DES_CBCUpdate (&context->cipherContext.des, output, input, len); + break; + case EA_DESX_CBC: + DESX_CBCUpdate (&context->cipherContext.desx, output, input, len); + break; + case EA_DES_EDE2_CBC: + case EA_DES_EDE3_CBC: + DES3_CBCUpdate (&context->cipherContext.des3, output, input, len); + } +} + +static void RestartCipher(context) +R_ENVELOPE_CTX *context; +{ + switch(context->encryptionAlgorithm) { + case EA_DES_CBC: + DES_CBCRestart (&context->cipherContext.des); + break; + case EA_DESX_CBC: + DESX_CBCRestart (&context->cipherContext.desx); + break; + case EA_DES_EDE2_CBC: + case EA_DES_EDE3_CBC: + DES3_CBCRestart (&context->cipherContext.des3); + } +} diff --git a/source/r_keygen.c b/source/r_keygen.c old mode 100755 new mode 100644 index 24eda19..6e47806 --- a/source/r_keygen.c +++ b/source/r_keygen.c @@ -1,7 +1,7 @@ /* R_KEYGEN.C - key-pair generation for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. diff --git a/source/r_random.c b/source/r_random.c old mode 100755 new mode 100644 index 3bd8346..0fe523d --- a/source/r_random.c +++ b/source/r_random.c @@ -1,222 +1,222 @@ -/* - R_RANDOM.C - random objects for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - Random Objects routines, based heavily on RSAREF(tm) random objects - code. New routines REQUIRE and ANSI Standard C compiler that has - clock() and time() functions. - - All Trademarks Acknowledged. - - Revisions History. - 0.90 First revision, initial version relied heavily - on RSAREF(tm) compatible code. - - 0.91 Current revision, minor improvements to original - version. New routines added. - R_RandomCreate, R_RandomMix - Compiler must has ANSI standard time routines for new routines - to operate fully. - - 1.01 Modifications to R_RandomCreate and R_RandomMix to - introduce better random number creation system. The old - R_RandomMix had a minor flaw as it didn't flush the old output - from the object, second added that little extra to the seed - for R_RandomCreate. -*/ - -#include -#include - -#ifdef MSDOS - #include -#endif - -#include "rsaeuro.h" -#include "r_random.h" - -#define RANDOM_BYTES_RQ 256 - /* We use more seed data for an internally created object */ -#define RANDOM_BYTES_RQINT 512 - -#define MIX_CNT 16 - -/* Set up, random object ready for seeding. */ - -int R_RandomInit(random) -R_RANDOM_STRUCT *random; /* new random structure */ -{ - /* clear and setup object for seeding */ - R_memset((POINTER)random->state, 0, sizeof(random->state)); - random->outputAvailable = 0; - random->bytesNeeded = RANDOM_BYTES_RQ; - - return(IDOK); -} - - - -int R_RandomUpdate(random, block, len) -R_RANDOM_STRUCT *random; /* random structure */ -unsigned char *block; /* block of values to mix in */ -unsigned int len; /* length of block */ -{ - MD5_CTX context; - BYTE digest[16]; - unsigned int i, j; - - MD5Init(&context); - MD5Update(&context, block, len); - MD5Final(digest, &context); - - /* add digest to state */ - - for(j = 0, i = 16; i > 0; i--) { - j += random->state[i-1] + digest[i-1]; - random->state[i-1] = (BYTE)j; - j >>= 8; - } - - if(random->bytesNeeded < len) - random->bytesNeeded = 0; - else - random->bytesNeeded -= len; - - /* Clear sensitive information. */ - - R_memset((POINTER)digest, 0, sizeof (digest)); - j = 0; - - return(IDOK); -} - -/* Get the number of seed byte still required by the object */ - -int R_GetRandomBytesNeeded(bytesNeeded, random) -unsigned int *bytesNeeded; /* number of mix-in bytes needed */ -R_RANDOM_STRUCT *random; /* random structure */ -{ - *bytesNeeded = random->bytesNeeded; - - return(IDOK); -} - -int R_GenerateBytes(block, len, random) -unsigned char *block; /* block */ -unsigned int len; /* length of block */ -R_RANDOM_STRUCT *random; /* random structure */ -{ - MD5_CTX context; - unsigned int avail, i; - - if(random->bytesNeeded) - return(RE_NEED_RANDOM); - - avail = random->outputAvailable; - - while(avail < len) { - R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], avail); - len -= avail; - block += avail; - - /* generate new output */ - - MD5Init(&context); - MD5Update(&context, random->state, 16); - MD5Final(random->output, &context); - avail = 16; - - /* increment state */ - for(i = 16; i > 0; i--) - if(random->state[i-1]++) - break; - } - - R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], len); - random->outputAvailable = avail - len; - - return(IDOK); -} - -/* Clear Random object when finished. */ - -void R_RandomFinal(random) -R_RANDOM_STRUCT *random; /* random structure */ -{ - R_memset((POINTER)random, 0, sizeof(R_RANDOM_STRUCT)); -} - -/* Create Random object, seed ready for use. - Requires ANSI Standard time routines to provide seed data. -*/ - -void R_RandomCreate(random) -R_RANDOM_STRUCT *random; /* random structure */ -{ - unsigned int bytes; - clock_t cnow; - time_t t; - struct tm *gmt; - - /* clear and setup object for seeding */ - R_memset((POINTER)random->state, 0, sizeof(random->state)); - random->outputAvailable = 0; - random->bytesNeeded = RANDOM_BYTES_RQINT; /* using internal value */ - - /* Add data to random object */ - while(random->bytesNeeded) { - t = time(NULL); /* use for seed data */ - gmt = gmtime(&t); - cnow = clock(); - - R_RandomUpdate(random, (POINTER)gmt, sizeof(struct tm)); - R_RandomUpdate(random, &cnow, sizeof(clock_t)); - } - - /* Clean Up time data */ - R_memset((POINTER)gmt, 0, sizeof(struct tm)); - cnow = 0; - t = 0; -} - -/* Mix up state of the current random structure. - Again requires both clock functions this just adds something - extra to the state, then refreshes the output. -*/ - -void R_RandomMix(random) -R_RANDOM_STRUCT *random; -{ - unsigned int i; - MD5_CTX context; - - for(i = 0; i < 16; i++) { - random->state[i] ^= (char) clock(); - random->state[15-i] ^= (char) time(NULL); - } - - /* Clear any old state with new data */ - - MD5Init(&context); - MD5Update(&context, random->state, 16); - MD5Final(random->output, &context); - - /* tell R_GenerateBytes there is new output */ - - random->outputAvailable = 16; - -} - - - +/* + R_RANDOM.C - random objects for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + Random Objects routines, based heavily on RSAREF(tm) random objects + code. New routines REQUIRE and ANSI Standard C compiler that has + clock() and time() functions. + + All Trademarks Acknowledged. + + Revisions History. + 0.90 First revision, initial version relied heavily + on RSAREF(tm) compatible code. + + 0.91 Current revision, minor improvements to original + version. New routines added. + R_RandomCreate, R_RandomMix + Compiler must has ANSI standard time routines for new routines + to operate fully. + + 1.01 Modifications to R_RandomCreate and R_RandomMix to + introduce better random number creation system. The old + R_RandomMix had a minor flaw as it didn't flush the old output + from the object, second added that little extra to the seed + for R_RandomCreate. +*/ + +#include +#include + +#ifdef MSDOS + #include +#endif + +#include "rsaeuro.h" +#include "r_random.h" + +#define RANDOM_BYTES_RQ 256 + /* We use more seed data for an internally created object */ +#define RANDOM_BYTES_RQINT 512 + +#define MIX_CNT 16 + +/* Set up, random object ready for seeding. */ + +int R_RandomInit(random) +R_RANDOM_STRUCT *random; /* new random structure */ +{ + /* clear and setup object for seeding */ + R_memset((POINTER)random->state, 0, sizeof(random->state)); + random->outputAvailable = 0; + random->bytesNeeded = RANDOM_BYTES_RQ; + + return(IDOK); +} + + + +int R_RandomUpdate(random, block, len) +R_RANDOM_STRUCT *random; /* random structure */ +unsigned char *block; /* block of values to mix in */ +unsigned int len; /* length of block */ +{ + MD5_CTX context; + BYTE digest[16]; + unsigned int i, j; + + MD5Init(&context); + MD5Update(&context, block, len); + MD5Final(digest, &context); + + /* add digest to state */ + + for(j = 0, i = 16; i > 0; i--) { + j += random->state[i-1] + digest[i-1]; + random->state[i-1] = (BYTE)j; + j >>= 8; + } + + if(random->bytesNeeded < len) + random->bytesNeeded = 0; + else + random->bytesNeeded -= len; + + /* Clear sensitive information. */ + + R_memset((POINTER)digest, 0, sizeof (digest)); + j = 0; + + return(IDOK); +} + +/* Get the number of seed byte still required by the object */ + +int R_GetRandomBytesNeeded(bytesNeeded, random) +unsigned int *bytesNeeded; /* number of mix-in bytes needed */ +R_RANDOM_STRUCT *random; /* random structure */ +{ + *bytesNeeded = random->bytesNeeded; + + return(IDOK); +} + +int R_GenerateBytes(block, len, random) +unsigned char *block; /* block */ +unsigned int len; /* length of block */ +R_RANDOM_STRUCT *random; /* random structure */ +{ + MD5_CTX context; + unsigned int avail, i; + + if(random->bytesNeeded) + return(RE_NEED_RANDOM); + + avail = random->outputAvailable; + + while(avail < len) { + R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], avail); + len -= avail; + block += avail; + + /* generate new output */ + + MD5Init(&context); + MD5Update(&context, random->state, 16); + MD5Final(random->output, &context); + avail = 16; + + /* increment state */ + for(i = 16; i > 0; i--) + if(random->state[i-1]++) + break; + } + + R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], len); + random->outputAvailable = avail - len; + + return(IDOK); +} + +/* Clear Random object when finished. */ + +void R_RandomFinal(random) +R_RANDOM_STRUCT *random; /* random structure */ +{ + R_memset((POINTER)random, 0, sizeof(R_RANDOM_STRUCT)); +} + +/* Create Random object, seed ready for use. + Requires ANSI Standard time routines to provide seed data. +*/ + +void R_RandomCreate(random) +R_RANDOM_STRUCT *random; /* random structure */ +{ + unsigned int bytes; + clock_t cnow; + time_t t; + struct tm *gmt; + + /* clear and setup object for seeding */ + R_memset((POINTER)random->state, 0, sizeof(random->state)); + random->outputAvailable = 0; + random->bytesNeeded = RANDOM_BYTES_RQINT; /* using internal value */ + + /* Add data to random object */ + while(random->bytesNeeded) { + t = time(NULL); /* use for seed data */ + gmt = gmtime(&t); + cnow = clock(); + + R_RandomUpdate(random, (POINTER)gmt, sizeof(struct tm)); + R_RandomUpdate(random, (POINTER)&cnow, sizeof(clock_t)); + } + + /* Clean Up time data */ + R_memset((POINTER)gmt, 0, sizeof(struct tm)); + cnow = 0; + t = 0; +} + +/* Mix up state of the current random structure. + Again requires both clock functions this just adds something + extra to the state, then refreshes the output. +*/ + +void R_RandomMix(random) +R_RANDOM_STRUCT *random; +{ + unsigned int i; + MD5_CTX context; + + for(i = 0; i < 16; i++) { + random->state[i] ^= (unsigned char) clock(); + random->state[15-i] ^= (unsigned char) time(NULL); + } + + /* Clear any old state with new data */ + + MD5Init(&context); + MD5Update(&context, random->state, 16); + MD5Final(random->output, &context); + + /* tell R_GenerateBytes there is new output */ + + random->outputAvailable = 16; + +} + + + diff --git a/source/r_random.h b/source/r_random.h old mode 100755 new mode 100644 index a0b8328..f9ee5f3 --- a/source/r_random.h +++ b/source/r_random.h @@ -1,23 +1,21 @@ /* R_RANDOM.H - header file for R_RANDOM.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Random Number Routines Header File. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ int R_GenerateBytes PROTO_LIST diff --git a/source/r_stdlib.c b/source/r_stdlib.c old mode 100755 new mode 100644 index d68624e..29a2d4d --- a/source/r_stdlib.c +++ b/source/r_stdlib.c @@ -1,7 +1,7 @@ /* R_STDLIB.C - platform-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -26,15 +26,13 @@ 0.92 Current revision, modified to allow use of assembler versions or the ANSI standard equivalent versions. - - 1.00 23/6/95, Final Release Version */ #include "rsaeuro.h" /* Library Copyright Message */ -BYTE *Copyright[] = { "Copyright (c) J.S.A.Kapp 1994." }; +BYTE *Copyright[] = { "Copyright (c) J.S.A.Kapp 94-96." }; #ifndef USE_ANSI /* Secure memset routine */ @@ -87,4 +85,4 @@ unsigned int len; /* length of blocks */ } #endif /* USEASM */ -#endif /* USE_ANSI */ \ No newline at end of file +#endif /* USE_ANSI */ diff --git a/source/rsa.c b/source/rsa.c old mode 100755 new mode 100644 index 212fb9a..7d4ed06 --- a/source/rsa.c +++ b/source/rsa.c @@ -1,357 +1,363 @@ -/* - RSA.C - RSA routines for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - RSA encryption performed as defined in the PKCS (#1) by RSADSI. - - Revision history - 0.90 First revision, code produced very similar to that - of RSAREF(tm), still it worked fine. - - 0.91 Current revision, code altered to aid speeding up. - Used pointer accesses to arrays to speed up some parts, - mainly during the loops. -*/ - -#include "rsaeuro.h" -#include "r_random.h" -#include "rsa.h" -#include "nn.h" - -static int rsapublicfunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *)); -static int rsaprivatefunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); - -/* RSA encryption, according to RSADSI's PKCS #1. */ - -int RSAPublicEncrypt(output, outputLen, input, inputLen, publicKey, randomStruct) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - int status; - unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen; - - modulusLen = (publicKey->bits + 7) / 8; - - if(inputLen + 11 > modulusLen) - return(RE_LEN); - - *pkcsBlock = 0; /* PKCS Block Makeup */ - - /* block type 2 */ - *(pkcsBlock+1) = 2; - - for(i = 2; i < modulusLen - inputLen - 1; i++) { - /* Find nonzero random byte. */ - do { /* random bytes used to pad the PKCS Block */ - R_GenerateBytes(&byte, 1, randomStruct); - }while(byte == 0); - *(pkcsBlock+i) = byte; - } - /* separator */ - pkcsBlock[i++] = 0; - - R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); - - status = rsapublicfunc(output, outputLen, pkcsBlock, modulusLen, publicKey); - - /* Clear sensitive information. */ - - byte = 0; - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(status); -} - -/* RSA decryption, according to RSADSI's PKCS #1. */ - -int RSAPublicDecrypt(output, outputLen, input, inputLen, publicKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ -{ - int status; - unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen, pkcsBlockLen; - - modulusLen = (publicKey->bits + 7) / 8; - - if(inputLen > modulusLen) - return(RE_LEN); - - status = rsapublicfunc(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey); - if(status) - return(status); - - if(pkcsBlockLen != modulusLen) - return(RE_LEN); - - /* Require block type 1. */ - - if((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1)) - return(RE_DATA); - - for(i = 2; i < modulusLen-1; i++) - if(*(pkcsBlock+i) != 0xff) - break; - - /* separator check */ - - if(pkcsBlock[i++] != 0) - return(RE_DATA); - - *outputLen = modulusLen - i; - - if(*outputLen + 11 > modulusLen) - return(RE_DATA); - - R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); - - /* Clear sensitive information. */ - - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(IDOK); -} - -/* RSA encryption, according to RSADSI's PKCS #1. */ - -int RSAPrivateEncrypt(output, outputLen, input, inputLen, privateKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ -{ - int status; - unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen; - - modulusLen = (privateKey->bits + 7) / 8; - - if(inputLen + 11 > modulusLen) - return (RE_LEN); - - *pkcsBlock = 0; - /* block type 1 */ - *(pkcsBlock+1) = 1; - - for (i = 2; i < modulusLen - inputLen - 1; i++) - *(pkcsBlock+i) = 0xff; - - /* separator */ - pkcsBlock[i++] = 0; - - R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); - - status = rsaprivatefunc(output, outputLen, pkcsBlock, modulusLen, privateKey); - - /* Clear sensitive information. */ - - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(status); -} - -/* RSA decryption, according to RSADSI's PKCS #1. */ - -int RSAPrivateDecrypt(output, outputLen, input, inputLen, privateKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ -{ - int status; - unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen, pkcsBlockLen; - - modulusLen = (privateKey->bits + 7) / 8; - - if(inputLen > modulusLen) - return (RE_LEN); - - status = rsaprivatefunc(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey); - if(status) - return (status); - - if(pkcsBlockLen != modulusLen) - return (RE_LEN); - - /* We require block type 2. */ - - if((*pkcsBlock != 0) || (*(pkcsBlock+1) != 2)) - return (RE_DATA); - - for(i = 2; i < modulusLen-1; i++) - /* separator */ - if (*(pkcsBlock+i) == 0) - break; - - i++; - if(i >= modulusLen) - return(RE_DATA); - - *outputLen = modulusLen - i; - - if(*outputLen + 11 > modulusLen) - return(RE_DATA); - - R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); - - /* Clear sensitive information. */ - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(IDOK); -} - -/* Raw RSA public-key operation. Output has same length as modulus. - - Requires input < modulus. -*/ -static int rsapublicfunc(output, outputLen, input, inputLen, publicKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ -{ - NN_DIGIT c[MAX_NN_DIGITS], e[MAX_NN_DIGITS], m[MAX_NN_DIGITS], - n[MAX_NN_DIGITS]; - unsigned int eDigits, nDigits; - - - /* decode the required RSA function input data */ - NN_Decode(m, MAX_NN_DIGITS, input, inputLen); - NN_Decode(n, MAX_NN_DIGITS, publicKey->modulus, MAX_RSA_MODULUS_LEN); - NN_Decode(e, MAX_NN_DIGITS, publicKey->exponent, MAX_RSA_MODULUS_LEN); - - nDigits = NN_Digits(n, MAX_NN_DIGITS); - eDigits = NN_Digits(e, MAX_NN_DIGITS); - - if(NN_Cmp(m, n, nDigits) >= 0) - return(RE_DATA); - - *outputLen = (publicKey->bits + 7) / 8; - - /* Compute c = m^e mod n. To perform actual RSA calc.*/ - - NN_ModExp (c, m, e, eDigits, n, nDigits); - - /* encode output to standard form */ - NN_Encode (output, *outputLen, c, nDigits); - - /* Clear sensitive information. */ - - R_memset((POINTER)c, 0, sizeof(c)); - R_memset((POINTER)m, 0, sizeof(m)); - - return(IDOK); -} - -/* Raw RSA private-key operation. Output has same length as modulus. - - Requires input < modulus. -*/ - -static int rsaprivatefunc(output, outputLen, input, inputLen, privateKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ -{ - NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS], - dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS], - mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS], - qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; - unsigned int cDigits, nDigits, pDigits; - - /* decode required input data from standard form */ - NN_Decode(c, MAX_NN_DIGITS, input, inputLen); /* input */ - - /* private key data */ - NN_Decode(p, MAX_NN_DIGITS, privateKey->prime[0], MAX_RSA_PRIME_LEN); - NN_Decode(q, MAX_NN_DIGITS, privateKey->prime[1], MAX_RSA_PRIME_LEN); - NN_Decode(dP, MAX_NN_DIGITS, privateKey->primeExponent[0], MAX_RSA_PRIME_LEN); - NN_Decode(dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], MAX_RSA_PRIME_LEN); - NN_Decode(n, MAX_NN_DIGITS, privateKey->modulus, MAX_RSA_MODULUS_LEN); - NN_Decode(qInv, MAX_NN_DIGITS, privateKey->coefficient, MAX_RSA_PRIME_LEN); - /* work out lengths of input components */ - - cDigits = NN_Digits(c, MAX_NN_DIGITS); - pDigits = NN_Digits(p, MAX_NN_DIGITS); - nDigits = NN_Digits(n, MAX_NN_DIGITS); - - - if(NN_Cmp(c, n, nDigits) >= 0) - return(RE_DATA); - - *outputLen = (privateKey->bits + 7) / 8; - - /* Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. (Assumes q has - length at most pDigits, i.e., p > q.) - */ - - NN_Mod(cP, c, cDigits, p, pDigits); - NN_Mod(cQ, c, cDigits, q, pDigits); - - NN_AssignZero(mP, nDigits); - NN_ModExp(mP, cP, dP, pDigits, p, pDigits); - - NN_AssignZero(mQ, nDigits); - NN_ModExp(mQ, cQ, dQ, pDigits, q, pDigits); - - /* Chinese Remainder Theorem: - m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ. - */ - - if(NN_Cmp(mP, mQ, pDigits) >= 0) { - NN_Sub(t, mP, mQ, pDigits); - }else{ - NN_Sub(t, mQ, mP, pDigits); - NN_Sub(t, p, t, pDigits); - } - - NN_ModMult(t, t, qInv, p, pDigits); - NN_Mult(t, t, q, pDigits); - NN_Add(t, t, mQ, nDigits); - - /* encode output to standard form */ - NN_Encode (output, *outputLen, t, nDigits); - - /* Clear sensitive information. */ -/* - R_memset((POINTER)c, 0, sizeof(c)); - R_memset((POINTER)cP, 0, sizeof(cP)); - R_memset((POINTER)cQ, 0, sizeof(cQ)); - R_memset((POINTER)dP, 0, sizeof(dP)); - R_memset((POINTER)dQ, 0, sizeof(dQ)); - R_memset((POINTER)mP, 0, sizeof(mP)); - R_memset((POINTER)mQ, 0, sizeof(mQ)); - R_memset((POINTER)p, 0, sizeof(p)); - R_memset((POINTER)q, 0, sizeof(q)); - R_memset((POINTER)qInv, 0, sizeof(qInv)); - R_memset((POINTER)t, 0, sizeof(t)); -*/ - return(IDOK); -} +/* + RSA.C - RSA routines for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + RSA encryption performed as defined in the PKCS (#1) by RSADSI. + + Revision history + 0.90 First revision, code produced very similar to that + of RSAREF(tm), still it worked fine. + + 0.91 Second revision, code altered to aid speeding up. + Used pointer accesses to arrays to speed up some parts, + mainly during the loops. + + 1.03 Third revision, Random Structure initialization + double check, RSAPublicEncrypt can now return RE_NEED_RANDOM. +*/ + +#include "rsaeuro.h" +#include "r_random.h" +#include "rsa.h" +#include "nn.h" + +static int rsapublicfunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *)); +static int rsaprivatefunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); + +/* RSA encryption, according to RSADSI's PKCS #1. */ + +int RSAPublicEncrypt(output, outputLen, input, inputLen, publicKey, randomStruct) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + int status; + unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen; + + modulusLen = (publicKey->bits + 7) / 8; + + if(inputLen + 11 > modulusLen) + return(RE_LEN); + + R_GetRandomBytesNeeded(&i, randomStruct); + if(i != 0) + return(RE_NEED_RANDOM); + + *pkcsBlock = 0; /* PKCS Block Makeup */ + + /* block type 2 */ + *(pkcsBlock+1) = 2; + + for(i = 2; i < modulusLen - inputLen - 1; i++) { + /* Find nonzero random byte. */ + do { /* random bytes used to pad the PKCS Block */ + R_GenerateBytes(&byte, 1, randomStruct); + }while(byte == 0); + *(pkcsBlock+i) = byte; + } + + /* separator */ + pkcsBlock[i++] = 0; + + R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); + + status = rsapublicfunc(output, outputLen, pkcsBlock, modulusLen, publicKey); + + /* Clear sensitive information. */ + + byte = 0; + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(status); +} + +/* RSA decryption, according to RSADSI's PKCS #1. */ + +int RSAPublicDecrypt(output, outputLen, input, inputLen, publicKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ +{ + int status; + unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen, pkcsBlockLen; + + modulusLen = (publicKey->bits + 7) / 8; + + if(inputLen > modulusLen) + return(RE_LEN); + + status = rsapublicfunc(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey); + if(status) + return(status); + + if(pkcsBlockLen != modulusLen) + return(RE_LEN); + + /* Require block type 1. */ + + if((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1)) + return(RE_DATA); + + for(i = 2; i < modulusLen-1; i++) + if(*(pkcsBlock+i) != 0xff) + break; + + /* separator check */ + + if(pkcsBlock[i++] != 0) + return(RE_DATA); + + *outputLen = modulusLen - i; + + if(*outputLen + 11 > modulusLen) + return(RE_DATA); + + R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); + + /* Clear sensitive information. */ + + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(IDOK); +} + +/* RSA encryption, according to RSADSI's PKCS #1. */ + +int RSAPrivateEncrypt(output, outputLen, input, inputLen, privateKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ +{ + int status; + unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen; + + modulusLen = (privateKey->bits + 7) / 8; + + if(inputLen + 11 > modulusLen) + return (RE_LEN); + + *pkcsBlock = 0; + /* block type 1 */ + *(pkcsBlock+1) = 1; + + for (i = 2; i < modulusLen - inputLen - 1; i++) + *(pkcsBlock+i) = 0xff; + + /* separator */ + pkcsBlock[i++] = 0; + + R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); + + status = rsaprivatefunc(output, outputLen, pkcsBlock, modulusLen, privateKey); + + /* Clear sensitive information. */ + + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(status); +} + +/* RSA decryption, according to RSADSI's PKCS #1. */ + +int RSAPrivateDecrypt(output, outputLen, input, inputLen, privateKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ +{ + int status; + unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen, pkcsBlockLen; + + modulusLen = (privateKey->bits + 7) / 8; + + if(inputLen > modulusLen) + return (RE_LEN); + + status = rsaprivatefunc(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey); + if(status) + return (status); + + if(pkcsBlockLen != modulusLen) + return (RE_LEN); + + /* We require block type 2. */ + + if((*pkcsBlock != 0) || (*(pkcsBlock+1) != 2)) + return (RE_DATA); + + for(i = 2; i < modulusLen-1; i++) + /* separator */ + if (*(pkcsBlock+i) == 0) + break; + + i++; + if(i >= modulusLen) + return(RE_DATA); + + *outputLen = modulusLen - i; + + if(*outputLen + 11 > modulusLen) + return(RE_DATA); + + R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); + + /* Clear sensitive information. */ + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(IDOK); +} + +/* Raw RSA public-key operation. Output has same length as modulus. + + Requires input < modulus. +*/ +static int rsapublicfunc(output, outputLen, input, inputLen, publicKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ +{ + NN_DIGIT c[MAX_NN_DIGITS], e[MAX_NN_DIGITS], m[MAX_NN_DIGITS], + n[MAX_NN_DIGITS]; + unsigned int eDigits, nDigits; + + + /* decode the required RSA function input data */ + NN_Decode(m, MAX_NN_DIGITS, input, inputLen); + NN_Decode(n, MAX_NN_DIGITS, publicKey->modulus, MAX_RSA_MODULUS_LEN); + NN_Decode(e, MAX_NN_DIGITS, publicKey->exponent, MAX_RSA_MODULUS_LEN); + + nDigits = NN_Digits(n, MAX_NN_DIGITS); + eDigits = NN_Digits(e, MAX_NN_DIGITS); + + if(NN_Cmp(m, n, nDigits) >= 0) + return(RE_DATA); + + *outputLen = (publicKey->bits + 7) / 8; + + /* Compute c = m^e mod n. To perform actual RSA calc.*/ + + NN_ModExp (c, m, e, eDigits, n, nDigits); + + /* encode output to standard form */ + NN_Encode (output, *outputLen, c, nDigits); + + /* Clear sensitive information. */ + + R_memset((POINTER)c, 0, sizeof(c)); + R_memset((POINTER)m, 0, sizeof(m)); + + return(IDOK); +} + +/* Raw RSA private-key operation. Output has same length as modulus. + + Requires input < modulus. +*/ + +static int rsaprivatefunc(output, outputLen, input, inputLen, privateKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ +{ + NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS], + dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS], + mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS], + qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; + unsigned int cDigits, nDigits, pDigits; + + /* decode required input data from standard form */ + NN_Decode(c, MAX_NN_DIGITS, input, inputLen); /* input */ + + /* private key data */ + NN_Decode(p, MAX_NN_DIGITS, privateKey->prime[0], MAX_RSA_PRIME_LEN); + NN_Decode(q, MAX_NN_DIGITS, privateKey->prime[1], MAX_RSA_PRIME_LEN); + NN_Decode(dP, MAX_NN_DIGITS, privateKey->primeExponent[0], MAX_RSA_PRIME_LEN); + NN_Decode(dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], MAX_RSA_PRIME_LEN); + NN_Decode(n, MAX_NN_DIGITS, privateKey->modulus, MAX_RSA_MODULUS_LEN); + NN_Decode(qInv, MAX_NN_DIGITS, privateKey->coefficient, MAX_RSA_PRIME_LEN); + /* work out lengths of input components */ + + cDigits = NN_Digits(c, MAX_NN_DIGITS); + pDigits = NN_Digits(p, MAX_NN_DIGITS); + nDigits = NN_Digits(n, MAX_NN_DIGITS); + + + if(NN_Cmp(c, n, nDigits) >= 0) + return(RE_DATA); + + *outputLen = (privateKey->bits + 7) / 8; + + /* Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. (Assumes q has + length at most pDigits, i.e., p > q.) + */ + + NN_Mod(cP, c, cDigits, p, pDigits); + NN_Mod(cQ, c, cDigits, q, pDigits); + + NN_AssignZero(mP, nDigits); + NN_ModExp(mP, cP, dP, pDigits, p, pDigits); + + NN_AssignZero(mQ, nDigits); + NN_ModExp(mQ, cQ, dQ, pDigits, q, pDigits); + + /* Chinese Remainder Theorem: + m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ. + */ + + if(NN_Cmp(mP, mQ, pDigits) >= 0) { + NN_Sub(t, mP, mQ, pDigits); + }else{ + NN_Sub(t, mQ, mP, pDigits); + NN_Sub(t, p, t, pDigits); + } + + NN_ModMult(t, t, qInv, p, pDigits); + NN_Mult(t, t, q, pDigits); + NN_Add(t, t, mQ, nDigits); + + /* encode output to standard form */ + NN_Encode (output, *outputLen, t, nDigits); + + /* Clear sensitive information. */ + R_memset((POINTER)c, 0, sizeof(c)); + R_memset((POINTER)cP, 0, sizeof(cP)); + R_memset((POINTER)cQ, 0, sizeof(cQ)); + R_memset((POINTER)dP, 0, sizeof(dP)); + R_memset((POINTER)dQ, 0, sizeof(dQ)); + R_memset((POINTER)mP, 0, sizeof(mP)); + R_memset((POINTER)mQ, 0, sizeof(mQ)); + R_memset((POINTER)p, 0, sizeof(p)); + R_memset((POINTER)q, 0, sizeof(q)); + R_memset((POINTER)qInv, 0, sizeof(qInv)); + R_memset((POINTER)t, 0, sizeof(t)); + return(IDOK); +} diff --git a/source/rsa.h b/source/rsa.h old mode 100755 new mode 100644 index 55eadb2..d6b8c5e --- a/source/rsa.h +++ b/source/rsa.h @@ -1,23 +1,21 @@ /* RSA.H - header file for RSA.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - RSA Routines Header File. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ int RSAPublicEncrypt PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, diff --git a/source/rsa386.s b/source/rsa386.s old mode 100755 new mode 100644 index ff57daa..9ce6e6f --- a/source/rsa386.s +++ b/source/rsa386.s @@ -1,7 +1,7 @@ /* RSA386.s - processor-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF 2.0. @@ -31,8 +31,6 @@ Some speed increases where noticed with the addition of these functions. - - 1.00 23/6/95, Final Release Version */ /* Multipresecion Math Routines */ diff --git a/source/rsa68k.s b/source/rsa68k.s old mode 100755 new mode 100644 index ff51a43..baeb72c --- a/source/rsa68k.s +++ b/source/rsa68k.s @@ -1,7 +1,7 @@ /* RSA68K.S - processor-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF 2.0. @@ -34,8 +34,6 @@ Some speed increases where noticed with the addition of these functions. - - 1.00 23/6/95, Final Release Version */ /* R_STDLIB Routines */ diff --git a/source/rsaeuro.h b/source/rsaeuro.h old mode 100755 new mode 100644 index 26bbca0..5528f68 --- a/source/rsaeuro.h +++ b/source/rsaeuro.h @@ -1,311 +1,311 @@ -/* - RSAEURO.H - header file for RSAEURO cryptographic toolkit - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - This header file contains prototypes, and other definitions used - in and by RSAEURO. - - Revision history - 0.90 First revision, implements all of RSAREF.H plus some minor - changes. - - 0.91 Second revision, Fixed a couple of problems. SHS support - added to header file, digest contexts altered. - - 0.92 Third revision, add support at this level for the assembler - routines and the implementation of some routines using the ANSI C - equivalent. - - 0.93 Fourth revision, Library details section added, MD4 details - added to header file, digest contexts altered. -*/ - -#ifndef _RSAEURO_H_ -#define _RSAEURO_H_ - -#include - -#include "global.h" -#include "md2.h" /* allow access to others */ -#include "md4.h" -#include "md5.h" -#include "shs.h" -#include "nn.h" -#include "des.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Message-digest algorithms. */ - -#define DA_MD2 2 -#define DA_MD4 4 -#define DA_MD5 5 -#define DA_SHS 3 - -/* Encryption algorithms to be ored with digest algorithm in Seal and Open. */ - -#define EA_DES_CBC 1 -#define EA_DES_EDE2_CBC 2 -#define EA_DES_EDE3_CBC 3 -#define EA_DESX_CBC 4 - -/* RSA key lengths. */ - -#define MIN_RSA_MODULUS_BITS 508 -/* - PGP 2.6.2 Now allows 2048-bit keys changing below will allow this. - It does lengthen key generation slightly if the value is increased. -*/ -#define MAX_RSA_MODULUS_BITS 1024 -#define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8) -#define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2) -#define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8) - -/* Maximum lengths of encoded and encrypted content, as a function of - content length len. Also, inverse functions. */ - -#define ENCODED_CONTENT_LEN(len) (4*(len)/3 + 3) -#define ENCRYPTED_CONTENT_LEN(len) ENCODED_CONTENT_LEN ((len)+8) -#define DECODED_CONTENT_LEN(len) (3*(len)/4 + 1) -#define DECRYPTED_CONTENT_LEN(len) (DECODED_CONTENT_LEN (len) - 1) - -/* Maximum lengths of signatures, encrypted keys, encrypted - signatures, and message digests. */ - -#define MAX_SIGNATURE_LEN MAX_RSA_MODULUS_LEN -#define MAX_PEM_SIGNATURE_LEN ENCODED_CONTENT_LEN(MAX_SIGNATURE_LEN) -#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN -#define MAX_PEM_ENCRYPTED_KEY_LEN ENCODED_CONTENT_LEN(MAX_ENCRYPTED_KEY_LEN) -#define MAX_PEM_ENCRYPTED_SIGNATURE_LEN ENCRYPTED_CONTENT_LEN(MAX_SIGNATURE_LEN) -#define MAX_DIGEST_LEN 20 - -/* Maximum length of Diffie-Hellman parameters. */ - -#define DH_PRIME_LEN(bits) (((bits) + 7) / 8) - -/* Error codes. */ - -#define RE_CONTENT_ENCODING 0x0400 -#define RE_DATA 0x0401 -#define RE_DIGEST_ALGORITHM 0x0402 -#define RE_ENCODING 0x0403 -#define RE_KEY 0x0404 -#define RE_KEY_ENCODING 0x0405 -#define RE_LEN 0x0406 -#define RE_MODULUS_LEN 0x0407 -#define RE_NEED_RANDOM 0x0408 -#define RE_PRIVATE_KEY 0x0409 -#define RE_PUBLIC_KEY 0x040a -#define RE_SIGNATURE 0x040b -#define RE_SIGNATURE_ENCODING 0x040c -#define RE_ENCRYPTION_ALGORITHM 0x040d - -/* Library details. */ - -#define RSAEURO_VER_MAJ 1 -#define RSAEURO_VER_MIN 02 -#define RSAEURO_IDENT "RSAEURO" -#define RSAEURO_DATE "21/08/94" - -/* Internal Error Codes */ - -#define IDOK 0 -#define IDERROR 1 - -/* Internal defs. */ - -#define TRUE 1 -#define FALSE 0 - -/* Random structure. */ - -typedef struct { - unsigned int bytesNeeded; /* seed bytes required */ - unsigned char state[16]; /* state of object */ - unsigned int outputAvailable; /* number byte available */ - unsigned char output[16]; /* output bytes */ -} R_RANDOM_STRUCT; - -/* RSA public and private key. */ - -typedef struct { - unsigned short int bits; /* length in bits of modulus */ - unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ - unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ -} R_RSA_PUBLIC_KEY; - -typedef struct { - unsigned short int bits; /* length in bits of modulus */ - unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ - unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ - unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */ - unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */ - unsigned char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */ - unsigned char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */ -} R_RSA_PRIVATE_KEY; - -/* RSA prototype key. */ - -typedef struct { - unsigned int bits; /* length in bits of modulus */ - int useFermat4; /* public exponent (1 = F4, 0 = 3) */ -} R_RSA_PROTO_KEY; - -/* Diffie-Hellman parameters. */ - -typedef struct { - unsigned char *prime; /* prime */ - unsigned int primeLen; /* length of prime */ - unsigned char *generator; /* generator */ - unsigned int generatorLen; /* length of generator */ -} R_DH_PARAMS; - -/* digest algorithm context */ - -typedef struct { - int digestAlgorithm; /* digest type */ - union { /* digest sub-context */ - MD2_CTX md2; - MD4_CTX md4; - MD5_CTX md5; - SHS_CTX shs; - } context; -} R_DIGEST_CTX; - -/* signature context */ - -typedef struct { - R_DIGEST_CTX digestContext; -} R_SIGNATURE_CTX; - -/* envelope context */ - -typedef struct { - int encryptionAlgorithm; /* encryption type */ - union { /* encryption sub-context */ - DES_CBC_CTX des; - DES3_CBC_CTX des3; - DESX_CBC_CTX desx; - } cipherContext; - - unsigned char buffer[8]; /* data buffer */ - unsigned int bufferLen; /* buffer length */ -} R_ENVELOPE_CTX; - -/* Random Structures Routines. */ - -int R_RandomInit PROTO_LIST ((R_RANDOM_STRUCT *)); -int R_RandomUpdate PROTO_LIST ((R_RANDOM_STRUCT *, unsigned char *, unsigned int)); -int R_GetRandomBytesNeeded PROTO_LIST ((unsigned int *, R_RANDOM_STRUCT *)); -void R_RandomFinal PROTO_LIST ((R_RANDOM_STRUCT *)); -void R_RandomCreate PROTO_LIST ((R_RANDOM_STRUCT *random)); -void R_RandomMix PROTO_LIST ((R_RANDOM_STRUCT *random)); -int R_GenerateBytes(unsigned char *block, unsigned int len, - R_RANDOM_STRUCT *random); - -/* Cryptographic procedures. */ - -int R_DigestInit PROTO_LIST ((R_DIGEST_CTX *, int)); -int R_DigestUpdate PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, - unsigned int)); -int R_DigestFinal PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, - unsigned int *)); -int R_SignInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); -int R_SignUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int)); -int R_SignFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int *, R_RSA_PRIVATE_KEY *)); -int R_VerifyInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); -int R_VerifyUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int)); -int R_VerifyFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int, R_RSA_PUBLIC_KEY *)); -int R_SealInit PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char **, unsigned int *, unsigned char [8], - unsigned int, R_RSA_PUBLIC_KEY **, int, R_RANDOM_STRUCT *)); -int R_SealUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); -int R_SealFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *)); -int R_OpenInit PROTO_LIST ((R_ENVELOPE_CTX *, int, unsigned char *, - unsigned int, unsigned char [8], R_RSA_PRIVATE_KEY *)); -int R_OpenUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); -int R_OpenFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *)); - -/* Cryptographic enhancements. */ - -int R_SignPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, - unsigned char *, unsigned int, int, int, R_RSA_PRIVATE_KEY *)); -int R_SignBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int, - R_RSA_PRIVATE_KEY *)); -int R_VerifyPEMSignature PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, - unsigned char *, unsigned int, int, int, R_RSA_PUBLIC_KEY *)); -int R_VerifyBlockSignature PROTO_LIST ((unsigned char *, unsigned int, - unsigned char *, unsigned int, int, R_RSA_PUBLIC_KEY *)); -int R_SealPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, - unsigned char *, unsigned int *, unsigned char [8], unsigned char *, - unsigned int, int, R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, - R_RANDOM_STRUCT *)); -int R_OpenPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, - unsigned char *, unsigned int, unsigned char *, unsigned int, - unsigned char [8], int, R_RSA_PRIVATE_KEY *, R_RSA_PUBLIC_KEY *)); -int R_DigestBlock PROTO_LIST ((unsigned char *, unsigned int *, - unsigned char *, unsigned int, int)); - -int R_DecryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); -int R_EncryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); - -/* Printable ASCII encoding and decoding. */ - -int R_EncodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, - unsigned char *, unsigned int)); -int R_DecodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, - unsigned char *, unsigned int)); - -/* Key-pair generation. */ - -int R_GeneratePEMKeys PROTO_LIST ((R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, - R_RSA_PROTO_KEY *, R_RANDOM_STRUCT *)); - -/* Diffie-Hellman key agreement. */ - -int R_GenerateDHParams PROTO_LIST ((R_DH_PARAMS *, unsigned int, - unsigned int, R_RANDOM_STRUCT *)); -int R_SetupDHAgreement PROTO_LIST ((unsigned char *, unsigned char *, - unsigned int, R_DH_PARAMS *, R_RANDOM_STRUCT *)); -int R_ComputeDHAgreedKey PROTO_LIST ((unsigned char *, unsigned char *, - unsigned char *, unsigned int, R_DH_PARAMS *)); - -/* Standard library routines. */ - -#ifdef USE_ANSI -#define R_memset(x, y, z) memset(x, y, z) -#define R_memcpy(x, y, z) memcpy(x, y, z) -#define R_memcmp(x, y, z) memcmp(x, y, z) -#else -void R_memset PROTO_LIST ((POINTER, int, unsigned int)); -void R_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); -int R_memcmp PROTO_LIST ((POINTER, POINTER, unsigned int)); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _RSAEURO_H_ */ +/* + RSAEURO.H - header file for RSAEURO cryptographic toolkit + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + This header file contains prototypes, and other definitions used + in and by RSAEURO. + + Revision history + 0.90 First revision, implements all of RSAREF.H plus some minor + changes. + + 0.91 Second revision, Fixed a couple of problems. SHS support + added to header file, digest contexts altered. + + 0.92 Third revision, add support at this level for the assembler + routines and the implementation of some routines using the ANSI C + equivalent. + + 0.93 Fourth revision, Library details section added, MD4 details + added to header file, digest contexts altered. +*/ + +#ifndef _RSAEURO_H_ +#define _RSAEURO_H_ + +#include + +#include "global.h" +#include "md2.h" /* allow access to others */ +#include "md4.h" +#include "md5.h" +#include "shs.h" +#include "nn.h" +#include "des.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Message-digest algorithms. */ + +#define DA_MD2 2 +#define DA_MD4 4 +#define DA_MD5 5 +#define DA_SHS 3 + +/* Encryption algorithms to be ored with digest algorithm in Seal and Open. */ + +#define EA_DES_CBC 1 +#define EA_DES_EDE2_CBC 2 +#define EA_DES_EDE3_CBC 3 +#define EA_DESX_CBC 4 + +/* RSA key lengths. */ + +#define MIN_RSA_MODULUS_BITS 508 +/* + PGP 2.6.2 Now allows 2048-bit keys changing below will allow this. + It does lengthen key generation slightly if the value is increased. +*/ +#define MAX_RSA_MODULUS_BITS 1024 +#define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8) +#define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2) +#define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8) + +/* Maximum lengths of encoded and encrypted content, as a function of + content length len. Also, inverse functions. */ + +#define ENCODED_CONTENT_LEN(len) (4*(len)/3 + 3) +#define ENCRYPTED_CONTENT_LEN(len) ENCODED_CONTENT_LEN ((len)+8) +#define DECODED_CONTENT_LEN(len) (3*(len)/4 + 1) +#define DECRYPTED_CONTENT_LEN(len) (DECODED_CONTENT_LEN (len) - 1) + +/* Maximum lengths of signatures, encrypted keys, encrypted + signatures, and message digests. */ + +#define MAX_SIGNATURE_LEN MAX_RSA_MODULUS_LEN +#define MAX_PEM_SIGNATURE_LEN ENCODED_CONTENT_LEN(MAX_SIGNATURE_LEN) +#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN +#define MAX_PEM_ENCRYPTED_KEY_LEN ENCODED_CONTENT_LEN(MAX_ENCRYPTED_KEY_LEN) +#define MAX_PEM_ENCRYPTED_SIGNATURE_LEN ENCRYPTED_CONTENT_LEN(MAX_SIGNATURE_LEN) +#define MAX_DIGEST_LEN 20 + +/* Maximum length of Diffie-Hellman parameters. */ + +#define DH_PRIME_LEN(bits) (((bits) + 7) / 8) + +/* Error codes. */ + +#define RE_CONTENT_ENCODING 0x0400 +#define RE_DATA 0x0401 +#define RE_DIGEST_ALGORITHM 0x0402 +#define RE_ENCODING 0x0403 +#define RE_KEY 0x0404 +#define RE_KEY_ENCODING 0x0405 +#define RE_LEN 0x0406 +#define RE_MODULUS_LEN 0x0407 +#define RE_NEED_RANDOM 0x0408 +#define RE_PRIVATE_KEY 0x0409 +#define RE_PUBLIC_KEY 0x040a +#define RE_SIGNATURE 0x040b +#define RE_SIGNATURE_ENCODING 0x040c +#define RE_ENCRYPTION_ALGORITHM 0x040d + +/* Library details. */ + +#define RSAEURO_VER_MAJ 1 +#define RSAEURO_VER_MIN 02 +#define RSAEURO_IDENT "RSAEURO" +#define RSAEURO_DATE "21/08/94" + +/* Internal Error Codes */ + +#define IDOK 0 +#define IDERROR 1 + +/* Internal defs. */ + +#define TRUE 1 +#define FALSE 0 + +/* Random structure. */ + +typedef struct { + unsigned int bytesNeeded; /* seed bytes required */ + unsigned char state[16]; /* state of object */ + unsigned int outputAvailable; /* number byte available */ + unsigned char output[16]; /* output bytes */ +} R_RANDOM_STRUCT; + +/* RSA public and private key. */ + +typedef struct { + unsigned short int bits; /* length in bits of modulus */ + unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ + unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ +} R_RSA_PUBLIC_KEY; + +typedef struct { + unsigned short int bits; /* length in bits of modulus */ + unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ + unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ + unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */ + unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */ + unsigned char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */ + unsigned char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */ +} R_RSA_PRIVATE_KEY; + +/* RSA prototype key. */ + +typedef struct { + unsigned int bits; /* length in bits of modulus */ + int useFermat4; /* public exponent (1 = F4, 0 = 3) */ +} R_RSA_PROTO_KEY; + +/* Diffie-Hellman parameters. */ + +typedef struct { + unsigned char *prime; /* prime */ + unsigned int primeLen; /* length of prime */ + unsigned char *generator; /* generator */ + unsigned int generatorLen; /* length of generator */ +} R_DH_PARAMS; + +/* digest algorithm context */ + +typedef struct { + int digestAlgorithm; /* digest type */ + union { /* digest sub-context */ + MD2_CTX md2; + MD4_CTX md4; + MD5_CTX md5; + SHS_CTX shs; + } context; +} R_DIGEST_CTX; + +/* signature context */ + +typedef struct { + R_DIGEST_CTX digestContext; +} R_SIGNATURE_CTX; + +/* envelope context */ + +typedef struct { + int encryptionAlgorithm; /* encryption type */ + union { /* encryption sub-context */ + DES_CBC_CTX des; + DES3_CBC_CTX des3; + DESX_CBC_CTX desx; + } cipherContext; + + unsigned char buffer[8]; /* data buffer */ + unsigned int bufferLen; /* buffer length */ +} R_ENVELOPE_CTX; + +/* Random Structures Routines. */ + +int R_RandomInit PROTO_LIST ((R_RANDOM_STRUCT *)); +int R_RandomUpdate PROTO_LIST ((R_RANDOM_STRUCT *, unsigned char *, unsigned int)); +int R_GetRandomBytesNeeded PROTO_LIST ((unsigned int *, R_RANDOM_STRUCT *)); +void R_RandomFinal PROTO_LIST ((R_RANDOM_STRUCT *)); +void R_RandomCreate PROTO_LIST ((R_RANDOM_STRUCT *random)); +void R_RandomMix PROTO_LIST ((R_RANDOM_STRUCT *random)); +int R_GenerateBytes(unsigned char *block, unsigned int len, + R_RANDOM_STRUCT *random); + +/* Cryptographic procedures. */ + +int R_DigestInit PROTO_LIST ((R_DIGEST_CTX *, int)); +int R_DigestUpdate PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, + unsigned int)); +int R_DigestFinal PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, + unsigned int *)); +int R_SignInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); +int R_SignUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int)); +int R_SignFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int *, R_RSA_PRIVATE_KEY *)); +int R_VerifyInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); +int R_VerifyUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int)); +int R_VerifyFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int, R_RSA_PUBLIC_KEY *)); +int R_SealInit PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char **, unsigned int *, unsigned char [8], + unsigned int, R_RSA_PUBLIC_KEY **, int, R_RANDOM_STRUCT *)); +int R_SealUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); +int R_SealFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *)); +int R_OpenInit PROTO_LIST ((R_ENVELOPE_CTX *, int, unsigned char *, + unsigned int, unsigned char [8], R_RSA_PRIVATE_KEY *)); +int R_OpenUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); +int R_OpenFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *)); + +/* Cryptographic enhancements. */ + +int R_SignPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, + unsigned char *, unsigned int, int, int, R_RSA_PRIVATE_KEY *)); +int R_SignBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int, + R_RSA_PRIVATE_KEY *)); +int R_VerifyPEMSignature PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, + unsigned char *, unsigned int, int, int, R_RSA_PUBLIC_KEY *)); +int R_VerifyBlockSignature PROTO_LIST ((unsigned char *, unsigned int, + unsigned char *, unsigned int, int, R_RSA_PUBLIC_KEY *)); +int R_SealPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, + unsigned char *, unsigned int *, unsigned char [8], unsigned char *, + unsigned int, int, R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, + R_RANDOM_STRUCT *)); +int R_OpenPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, + unsigned char *, unsigned int, unsigned char *, unsigned int, + unsigned char [8], int, R_RSA_PRIVATE_KEY *, R_RSA_PUBLIC_KEY *)); +int R_DigestBlock PROTO_LIST ((unsigned char *, unsigned int *, + unsigned char *, unsigned int, int)); + +int R_DecryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); +int R_EncryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); + +/* Printable ASCII encoding and decoding. */ + +int R_EncodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, + unsigned char *, unsigned int)); +int R_DecodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, + unsigned char *, unsigned int)); + +/* Key-pair generation. */ + +int R_GeneratePEMKeys PROTO_LIST ((R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, + R_RSA_PROTO_KEY *, R_RANDOM_STRUCT *)); + +/* Diffie-Hellman key agreement. */ + +int R_GenerateDHParams PROTO_LIST ((R_DH_PARAMS *, unsigned int, + unsigned int, R_RANDOM_STRUCT *)); +int R_SetupDHAgreement PROTO_LIST ((unsigned char *, unsigned char *, + unsigned int, R_DH_PARAMS *, R_RANDOM_STRUCT *)); +int R_ComputeDHAgreedKey PROTO_LIST ((unsigned char *, unsigned char *, + unsigned char *, unsigned int, R_DH_PARAMS *)); + +/* Standard library routines. */ + +#ifdef USE_ANSI +#define R_memset(x, y, z) memset(x, y, z) +#define R_memcpy(x, y, z) memcpy(x, y, z) +#define R_memcmp(x, y, z) memcmp(x, y, z) +#else +void R_memset PROTO_LIST ((POINTER, int, unsigned int)); +void R_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); +int R_memcmp PROTO_LIST ((POINTER, POINTER, unsigned int)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _RSAEURO_H_ */ diff --git a/source/rsaref.h b/source/rsaref.h old mode 100755 new mode 100644 index 4f47eb9..3d13f68 --- a/source/rsaref.h +++ b/source/rsaref.h @@ -1,24 +1,22 @@ /* RSAREF.H - header file for RSAEURO cryptographic toolkit - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - This header file is used to launch the RSAEURO.H header file. - Provided for compatiblity with RSAREF(tm). + Provided for compatiblity with RSAREF. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _RSAREF_H_ diff --git a/source/rsasparc.s b/source/rsasparc.s old mode 100755 new mode 100644 index d69c92c..71f0605 --- a/source/rsasparc.s +++ b/source/rsasparc.s @@ -1,7 +1,7 @@ /* RSASPARC.S - processor-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF 2.0. @@ -30,7 +30,7 @@ _NN_Encode, _NN_AssignZero, _NN_Zero, _NN_Cmp. - 1.00 23/6/95, Final Release Version + */ /* Math Routines */ diff --git a/source/shs.h b/source/shs.h old mode 100755 new mode 100644 index 78f64e8..f149815 --- a/source/shs.h +++ b/source/shs.h @@ -1,23 +1,23 @@ /* SHS.H - header file for Secure Hash Standard Code - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Secure Hash Standard Code header file. - Revision 1.00. - JSAK 23/6/95, Final Release Version + Revision 1.00. - JSAK + + Revision 1.03. - JSAK */ #ifndef _SHS_H_ @@ -43,8 +43,8 @@ typedef struct { } SHS_CTX; void SHSInit PROTO_LIST ((SHS_CTX *)); -void SHSUpdate PROTO_LIST ((SHS_CTX *, BYTE *, int )); -void SHSFinal PROTO_LIST ((SHS_CTX *)); +void SHSUpdate PROTO_LIST ((SHS_CTX *, unsigned char *, int )); +void SHSFinal PROTO_LIST ((unsigned char *, SHS_CTX *)); #ifdef __cplusplus } diff --git a/source/shsc.c b/source/shsc.c old mode 100755 new mode 100644 index 5c7143b..3113263 --- a/source/shsc.c +++ b/source/shsc.c @@ -1,7 +1,7 @@ /* SHSC.C - Secure Hash Standard Code - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -19,7 +19,8 @@ 0.90 first revision, initial implementation of the secure hash standard FIPS PUB 180. - 1.00 23/6/95, Final Release Version + 1.03 second revision, SHSFinal modified to output to a char + array specified by the user. */ @@ -31,22 +32,22 @@ #define K1 0x5A827999L /* Rounds 0-19 */ #define K2 0x6ED9EBA1L /* Rounds 20-39 */ #define K3 0x8F1BBCDCL /* Rounds 40-59 */ -#define K4 0xCA62C1D6L /* Rounds 60-79 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ /* SHS initial values */ #define Ainit 0x67452301L #define Binit 0xEFCDAB89L -#define Cinit 0x98BADCFEL -#define Dinit 0x10325476L -#define Einit 0xC3D2E1F0L +#define Cinit 0x98BADCFEL +#define Dinit 0x10325476L +#define Einit 0xC3D2E1F0L /* The SHS f()-functions */ -#define f1(x,y,z) (( x & y ) | ( ~x & z )) /* Rounds 0-19 */ +#define f1(x,y,z) (( x & y ) | ( ~x & z )) /* Rounds 0-19 */ #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ #define f3(x,y,z) (( x & y ) | ( x & z ) | ( y & z )) /* Rounds 40-59 */ -#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ /* 32-bit rotate - kludged with shifts */ @@ -105,6 +106,7 @@ UINT4 A, B, C, D, E; static void byteReverse PROTO_LIST ((UINT4 *, int )); static void SHSTransform PROTO_LIST ((SHS_CTX *)); +static void Encode PROTO_LIST((unsigned char *, UINT4 *, unsigned int)); /* Initialize the SHS values */ @@ -124,8 +126,8 @@ SHS_CTX *context; /* context */ /* Update SHS for a block of data. - This code assumes that the buffer size is a multiple of - SHS_BLOCKSIZE bytes long. + This code assumes that the buffer size is a multiple of + SHS_BLOCKSIZE bytes long. */ void SHSUpdate(context, buffer, count) @@ -153,11 +155,12 @@ int count; /* length of input block */ R_memcpy((POINTER)context->data, buffer, count); } -/* Finalize SHS hash, doesn't output a char value as yet. - That is on the todo list. +/* Finalize SHS hash, outputs to a unsigned char array. + array must be > 20 bytes in length. */ -void SHSFinal(context) +void SHSFinal(digest, context) +BYTE *digest; SHS_CTX *context; /* context */ { int count; @@ -190,6 +193,10 @@ SHS_CTX *context; /* context */ SHSTransform(context); byteReverse(context->data, SHS_DIGESTSIZE); + + Encode(digest, context->digest, 20); + + R_memset((POINTER)context, 0, sizeof(SHS_CTX)); } static void byteReverse(buffer, byteCount) @@ -281,6 +288,24 @@ SHS_CTX *context; context->digest[3] += D; context->digest[4] += E; + /* Clear sensitive information */ + R_memset((POINTER) W, 0, sizeof(W)); } +/* Encode SHS output in char array */ + +static void Encode(output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for(i = 0, j = 0; j < len; i++, j += 4) { + output[j+3] = (unsigned char)(input[i] & 0xff); + output[j+2] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+1] = (unsigned char)((input[i] >> 16) & 0xff); + output[j] = (unsigned char)((input[i] >> 24) & 0xff); + } +} diff --git a/source/targets.mak b/source/targets.mak old mode 100755 new mode 100644