RSAEURO

Version 1.03

  1. INTRODUCTION
  2. RANDOM NUMBERS
  3. MESSAGE DIGESTS
  4. DIGITAL SIGNATURE ROUTINES
  5. ENVELOPE PROCESSING
  6. PEM FUNCTIONS
  7. KEY GENERATION AND EXCHANGE
  8. RSA
  9. DES
  10. NATURAL NUMBER ARITHMETIC
  11. MEMORY MANIPULATION
  12. TECHNICAL INFORMATION
  13. APPENDIX A: FUNCTION CROSS-REFERENCE


INTRODUCTION

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

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. Functions
    1. R_RandomInit
    2. R_RandomUpdate
    3. R_GetRandomBytesNeeded
    4. R_GenerateBytes
    5. R_RandomFinal
    6. R_RandomCreate
    7. R_RandomMix

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. 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.
  3. "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. Functions
    1. R_DigestInit
    2. R_DigestUpdate
    3. R_DigestFinal
    4. R_DigestBlock
    5. MD2Init
    6. MD2Update
    7. MD2Final
    8. MD4Init
    9. MD4Update
    10. MD4Final
    11. MD5Init
    12. MD5Update
    13. MD5Final
    14. SHSInit
    15. SHSUpdate
    16. SHSFinal

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. Process the source data a block at a time, using R_DigestUpdate.
  3. 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. Functions
    1. R_SignInit
    2. R_SignUpdate
    3. R_SignFinal
    4. R_SignBlock
    5. R_VerifyInit
    6. R_VerifyUpdate
    7. R_VerifyFinal
    8. R_VerifyBlockSignature

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. Process the source data a block at a time using R_SignUpdate.
  3. 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. Process the source data a block at a time using R_VerifyUpdate.
  3. 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. Sealing data in digital envelopes
  3. Opening digital envelopes
  4. Functions
    1. R_SealInit
    2. R_SealUpdate
    3. R_SealFinal
    4. R_OpenInit
    5. R_OpenUpdate
    6. R_OpenFinal

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. Process the source data a block at a time, using R_SealUpdate.
  3. "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. Process the encrypted data a block at a time using R_OpenUpdate.
  3. 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. Functions
    1. R_EncodePEMBlock
    2. R_DecodePEMBlock
    3. R_SignPEMBlock
    4. R_VerifyPEMSignature
    5. R_SealPEMBlock
    6. R_OpenPEMBlock
    7. R_EncryptOpenPEMBlock
    8. R_DecryptOpenPEMBlock

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. RSA Key Generation
  3. Diffie-Hellman key agreement
  4. Functions
    1. R_GeneratePEMKeys
    2. R_GenerateDHParams
    3. R_SetupDHAgreement
    4. R_ComputeDHAgreedKey

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. The two parties wishing to communicate each generate public and private values using R_SetupDHAgreement, using the agreed on parameters.
  3. 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. Functions
    1. RSAPrivateEncrypt
    2. RSAPrivateDecrypt
    3. RSAPublicEncrypt
    4. RSAPublicDecrypt

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. Functions
    1. DES_CBCInit
    2. DES_CBCUpdate
    3. DES_CBCRestart
    4. DES3_CBCInit
    5. DES3_CBCRestart
    6. DES3_CBCUpdate
    7. DESX_CBCInit
    8. DESX_CBCRestart
    9. DESX_CBCUpdate

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. Representation of natural numbers
  3. Functions
    1. NN_Decode
    2. NN_Encode
    3. NN_Assign
    4. NN_AssignZero
    5. NN_Assign2Exp
    6. NN_Add
    7. NN_Sub
    8. NN_Mult
    9. NN_LShift
    10. NN_RShift
    11. NN_Div
    12. NN_Mod
    13. NN_ModMult
    14. NN_ModExp
    15. NN_ModInv
    16. NN_Gcd
    17. NN_Cmp
    18. NN_Zero
    19. NN_Digits
    20. NN_Bits
    21. GeneratePrime

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. Functions
    1. R_memset
    2. R_memcpy
    3. R_memcmp

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. Error Types
  3. RSAEURO Data Types
    1. R_RANDOM_STRUCT
    2. R_RSA_PUBLIC_KEY
    3. R_RSA_PRIVATE_KEY
    4. R_RSA_PROTO_KEY
    5. R_DH_PARAMS
    6. R_DIGEST_CTX
    7. R_SIGNATURE_CTX
    8. R_ENVELOPE_CTX
    9. MD2_CTX
    10. MD4_CTX
    11. MD5_CTX
    12. SHS_CTX
    13. DES_CBC_CTX
    14. DESX_CBC_CTX
    15. DES3_CBC_CTX
  4. Configuration parameters
  5. Platform-specific Configuration
    1. Types
    2. Defined macros
  6. References
    1. General
    2. RSA
    3. Diffie-Hellman
    4. Digest Algorithms
    5. DES
    6. Privacy-enhanced mail

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. RSAEURO Data Types A list and brief description of the major RSAEURO data types.
  3. Platform-specific configuration Platform-specific configuration information, including compiler settings and data structures.
  4. 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