rsaref/0407750006630000000000000000005626264741010464 5 0jissystem 1 0 rsaref/README1004440006630000000000004153705326645133010145 037777703401 1 0 RSAREF(TM): A Cryptographic Toolkit for Privacy-Enhanced Mail RSA Laboratories (A division of RSA Data Security, Inc.) January 5, 1993 This document copyright (C) 1992 RSA Laboratories, a division of RSA Data Security, Inc. License is granted to reproduce, copy, post, or distribute in any manner, provided this document is kept intact and no modifications, deletions, or additions are made. WHAT IS IT? RSAREF is a cryptographic toolkit designed to facilitate rapid deployment of Internet Privacy-Enhanced Mail (PEM) implementations. RSAREF represents the fruits of RSA Data Security's commitment to the U.S. Department of Defense's Advanced Research Projects Agency (DARPA) to provide free cryptographic source code in support of a PEM standard. RSA Laboratories offers RSAREF in expectation of PEM's forthcoming publication as an Internet standard. Part of RSA's commitment to DARPA was to authorize Trusted Information Systems of Glenwood, MD, to distribute a full PEM implementation. That implementation will be available this spring. RSAREF supports the following PEM-specified algorithms: o RSA encryption and key generation, as defined by RSA Laboratories' Public-Key Cryptography Standards (PKCS) o MD2 and MD5 message digests o DES (Data Encryption Standard) in cipher-block chaining mode RSAREF is written in the C programming language as a library that can be called from an application program. A simple PEM implementation can be built directly on top of RSAREF, together with message parsing and formatting routines and certificate-management routines. RSAREF is distributed with a demonstration program that shows how one might build such an implementation. The name "RSAREF" means "RSA reference." RSA Laboratories intends RSAREF to serve as a portable, educational, reference implementation of cryptography. WHAT YOU CAN (AND CANNOT) DO WITH RSAREF The license at the end of this note gives legal terms and conditions. Here's the layman's interpretation, for information only and with no legal weight: 1. You can use RSAREF in personal, non-commercial applications, as long as you follow the interface described in the RSAREF documentation. You can't use RSAREF in any commercial (moneymaking) manner of any type, nor can you use it to provide services of any kind to any other party. For information on commercial licenses of RSAREF-compatible products, please contact RSA Data Security. (Special arrangements are available for educational institutions and non-profit organizations.) 2. You can give others RSAREF and programs that interface to RSAREF, under the same terms and conditions as your RSAREF license. 3. You can modify RSAREF as required to port it to other operating systems and compilers, as long as you give a copy of the results to RSA Laboratories. Other changes require written consent. 4. You can't send RSAREF outside the United States or Canada, or give it to anyone who is not a U.S. or Canadian citizen and doesn't have a U.S. "green card." (These are U.S. State and Commerce Department requirements, because RSA and DES are export-controlled technologies.) HOW TO GET IT To obtain RSAREF, read the license at the end of the note and return a copy of the following paragraph by electronic mail to : I acknowledge that I have read the RSAREF Program License Agreement and understand and agree to be bound by its terms and conditions, including without limitation its restrictions on foreign reshipment of the Program and information related to the Program. The electronic mail address to which I am requesting that the program be transmitted is located in the United States of America or Canada and I am a United States citizen, a Canadian citizen, or a permanent resident of the United States. The RSAREF Program License Agreement is the complete and exclusive agreement between RSA Laboratories and me relating to the Program, and supersedes any proposal or prior agreement, oral or written, and any other communications between RSA Laboratories and me relating to the Program. RSAREF is distributed by electronic mail in UNIX(TM) "uuencoded" TAR format. When you receive it, store the contents of the message in a file, and run your operating system's "uudecode" and TAR programs. For example, suppose you store the contents of your message in the file 'contents'. You would run the commands: uudecode contents # produces rsaref.tar tar -xvf rsaref.tar RSAREF includes about 60 files organized into the following subdirectories: doc documentation on RSAREF and RDEMO install makefiles for various operating systems rdemo RDEMO demonstration program source RSAREF source code and include files test test scripts for RDEMO RSAREF is also available via anonymous FTP to 'rsa.com'. Along with RSAREF you can get RIPEM, Mark Riordan's RSAREF-based privacy-enhanced mail application, and an Emacs command interface to RIPEM. See the file 'README' in the FTP directory 'rsaref' for more information. USERS' GROUP RSA Laboratories maintains the electronic-mail users' group for discussion of RSAREF applications, bug fixes, etc. To join the users' group, send electronic mail to . REGISTRATION RSAREF users who register with RSA Laboratories are entitled to free RSAREF upgrades and bug fixes as soon as they become available and a 50% discount on selected RSA Data Security products. To register, send your name, address, and telephone number to . INNOVATION PRIZES RSA Laboratories will award cash prizes for the best applications built on RSAREF. If you'd like to submit an application, want to be on the review panel, or would like more details, please send electronic mail to . Applications are due December 31, 1992, and awards will be announced March 31, 1993. First prize is $5000, second prize is $2000, and there are five prizes of $1000. PUBLIC-KEY CERTIFICATION RSA Data Security offers public-key certification services conforming to forthcoming PEM standards. For more information, please send electronic mail to . PKCS: PUBLIC-KEY CRYPTOGRAPHY STANDARDS To obtain copies of RSA Laboratories' Public-Key Cryptography Standards (PKCS), send electronic mail to . OTHER QUESTIONS If you have questions on RSAREF software, licenses, export restrictions, or other RSA Laboratories offerings, send electronic mail to . AUTHORS RSAREF was written by the staff of RSA Laboratories with assistance from RSA Data Security's software engineers. The DES code is based on an implementation that Justin Reyneri did at Stanford University. Jim Hwang of Stanford wrote parts of the arithmetic code under contract to RSA Laboratories. ABOUT RSA LABORATORIES RSA Laboratories is the research and development division of RSA Data Security, Inc., the company founded by the inventors of the RSA public-key cryptosystem. RSA Laboratories reviews, designs and implements secure and efficient cryptosystems of all kinds. Its clients include government agencies, telecommunications companies, computer manufacturers, software developers, cable TV broadcasters, interactive video manufacturers, and satellite broadcast companies, among others. RSA Laboratories draws upon the talents of the following people: Len Adleman, distinguished associate - Ph.D., University of California, Berkeley; Henry Salvatori professor of computer science at University of Southern California; co-inventor of RSA public-key cryptosystem; co-founder of RSA Data Security, Inc. Taher Elgamal, senior associate - Ph.D., Stanford University; director of engineering at RSA Data Security, Inc.; inventor of Elgamal public-key cryptosystem based on discrete logarithms Martin Hellman, distinguished associate - Ph.D., Stanford University; professor of electrical engineering at Stanford University; co-inventor of public-key cryptography, exponential key exchange; IEEE fellow; IEEE Centennial Medal recipient Burt Kaliski, chief scientist - Ph.D., MIT; former visiting assistant professor at Rochester Institute of Technology; author of Public-Key Cryptography Standards; general chair of CRYPTO '91 Cetin Koc, associate - Ph.D., University of California, Santa Barbara; assistant professor at University of Houston Ron Rivest, distinguished associate - Ph.D., Stanford University; professor of computer science, MIT; co-inventor of RSA public-key cryptosystem; co-founder of RSA Data Security, Inc.; member of National Academy of Engineering; director of International Association for Cryptologic Research; program co-chair of ASIACRYPT '91 RSA Laboratories seeks the talents of other people as well. If you're interested, please write or call. ADDRESSES RSA Laboratories RSA Data Security, Inc. 100 Marine Parkway 100 Marine Parkway Redwood City, CA 94065 Redwood City, CA 94065 (415) 595-7703 (415) 595-8782 (415) 595-4126 (fax) (415) 595-1873 (fax) PKCS, RSAREF and RSA Laboratories are trademarks of RSA Data Security, Inc. All other company names and trademarks are not. ---------------------------------------------------------------------- RSA LABORATORIES PROGRAM LICENSE AGREEMENT RSA LABORATORIES, A DIVISION OF RSA DATA SECURITY, INC. ("RSA") GRANTS YOU A LICENSE AS FOLLOWS TO THE "RSAREF" PROGRAM: 1. LICENSE. RSA grants you a non-exclusive, non-transferable, perpetual (subject to the conditions of section 8) license for the "RSAREF" program (the "Program") and its associated documentation, subject to all of the following terms and conditions: a. to use the Program on any computer in your possession; b. to make copies of the Program for back-up purposes; c. to modify the Program in any manner for porting or performance improvement purposes (subject to Section 2) or to incorporate the Program into other computer programs for your own personal or internal use, provided that you provide RSA with a copy of any such modification or Application Program by electronic mail, and grant RSA a perpetual, royalty-free license to use and distribute such modifications and Application Programs on the terms set forth in this Agreement. d. to copy and distribute the Program and Application Programs in accordance with the limitations set forth in Section 2. "Application Programs" are programs which incorporate all or any portion of the Program 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 Program. 2. LIMITATIONS ON LICENSE. a. RSA owns the Program and its associated documentation and all copyrights therein. You may only use, copy, modify and distribute the Program as expressly provided for in this Agreement. You must reproduce and include this Agreement, RSA's copyright notices and disclaimer of warranty on any copy and its associated documentation. b. The Program and all Application Programs are to be used only for non-commercial purposes. However, media costs associated with the distribution of the Program or Application Programs may be recovered. c. The Program, if modified, must carry prominent notices stating that changes have been made, and the dates of any such changes. d. Prior permission from RSA is required for any modifications that access the Program through ways other than the published Program interface or for modifications to the Program interface. RSA will grant all reasonable requests for permission to make such modifications. 3. NO RSA OBLIGATION. You are solely responsible for all of your costs and expenses incurred in connection with the distribution of the Program or any Application Program hereunder, and RSA shall have no liability, obligation or responsibility therefor. RSA shall have no obligation to provide maintenance, support, upgrades or new releases to you or to any distributee of the Program or any Application Program. 4. NO WARRANTY OF PERFORMANCE. THE PROGRAM 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 PROGRAM IS ASSUMED BY YOU AND YOUR DISTRIBUTEES. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU AND YOUR DISTRIBUTEES (AND NOT RSA) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 5. LIMITATION OF LIABILITY. EXCEPT AS EXPRESSLY PROVIDED FOR IN SECTION 6 HEREINUNDER, NEITHER RSA NOR ANY OTHER PERSON WHO HAS BEEN INVOLVED IN THE CREATION, PRODUCTION, OR DELIVERY OF THE PROGRAM SHALL BE LIABLE TO YOU OR TO ANY OTHER PERSON FOR ANY DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF RSA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 6. PATENT INFRINGEMENT OBLIGATION. Subject to the limitations set forth below, RSA, at its own expense, shall: (i) defend, or at its option settle, any claim, suit or proceeding against you on the basis of infringement of any United States patent in the field of cryptography by the unmodified Program; and (ii) pay any final judgment or settlement entered against you on such issue in any such suit or proceeding defended by RSA. The obligations of RSA under this Section 6 are subject to: (i) RSA's having sole control of the defense of any such claim, suit or proceeding; (ii) your notifying RSA promptly in writing of each such claim, suit or proceeding and giving RSA authority to proceed as stated in this Section 6; and (iii) your giving RSA all information known to you relating to such claim, suit or proceeding and cooperating with RSA to defend any such claim, suit or proceeding. RSA shall have no obligation under this Section 6 with respect to any claim to the extent it is based upon (A) use of the Program as modified by any person other than RSA or use of any Application Program, where use of the unmodified Program would not constitute an infringement, or (B) use of the Program in a manner other than that permitted by this Agreement. THIS SECTION 6 SETS FORTH RSA'S ENTIRE OBLIGATION AND YOUR EXCLUSIVE REMEDIES CONCERNING CLAIMS FOR PROPRIETARY RIGHTS INFRINGEMENT. NOTE: Portions of the Program practice methods described in and subject to U.S. Patents Nos. 4,200,770, 4,218,582 and 4,405,829, and all foreign counterparts and equivalents, issued to Leland Stanford Jr. University and to Massachusetts Institute of Technology. Such patents are licensed to RSA by Public Key Partners of Sunnyvale, California, the holder of exclusive licensing rights. This Agreement does not grant or convey any interest whatsoever in such patents. 7. RSAREF is a non-commercial publication of cryptographic techniques. Portions of RSAREF have been published in the International Security Handbook and the August 1992 issue of Dr. Dobb's Journal. Privacy applications developed with RSAREF may be subject to export controls. If you are located in the United States and develop such applications, you are advised to consult with the State Department's Office of Defense Trade Controls. 8. TERM. The license granted hereunder is effective until terminated. You may terminate it at anytime by destroying the Program 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 Program through you so long as they are in compliance with the provisions of this license. 9. GENERAL a. This Agreement shall be governed by the laws of the State of California. b. Address all correspondence regarding this license to RSA's electronic mail address , or to RSA Laboratories ATTN: RSAREF Administrator 100 Marine Parkway, Suite 500 Redwood City, CA 94065 s written by the staff of RSA Laboratories with assistance from RSA Data Security's software engineers. The DES code is based on an implementation that Justin Rersaref/doc/0407750006630000000000000000005626264721007254 5 0 1 0 rsaref/doc/porting.txt1006440006630000000000000061305153737530012246 037777703401 1 0 RSAREF has been ported without modification (except for makefile) to the following platforms: Personal Computer running DOS Microsoft C v6.00a medium & large memory models Personal Computer running OS/2 Microsoft C v6.00a Macintosh running System 7 MPW 3.2 NeXTStation DECStation 3100 SPARCStation1 MicroVAX II running VMS ist - Ph.D., MIT; former visiting assistant professor at Rochester Institute of Technology; author of Public-Key rsaref/doc/scripts.txt1006440006630000000000000362305326646510012256 037777703401 1 0 RDEMO Test Scripts RSA Laboratories March 2, 1992 RDEMO comes with several test scripts that test RSAREF cryptographic operations of various key sizes. The test scripts are: '508test.in', '512test.in', '767test.in', '1024test.in', and 'md2test.in'. The scripts consists of RDEMO commands. To exercise a script, redirect RDEMO's input to the script. For example, on a UNIX system you would run the command rdemo < 508test.in to exercise the test script '508test.in'. The scripts work with a number of input files. Each script also produces output files that you can compare against reference files supplied with RDEMO. See the file 'rdemo.txt' in the 'doc' subdirectory for more on the demonstration program. '508test.in' script 1. Generates a 508-bit RSA key pair. 2. Outputs key to '508key.out' - compare to '508key'. 3. Verifies signature '508sig' on 'signfile' with 508-bit public key. 4. Opens envelope '508env' (signature '508env.sig', encrypted key '508env.key', initialization vector '508env.iv') with 508-bit private key, built-in user #1 private key. Outputs result to '508env.out' - read to verify. '512test.in' script 1. Verifies signature '512sig' on 'signfile' with built-in user #1 public key. 2. Opens envelope '512env' (encrypted signature '512env.sig', encrypted key '512env.key', initialization vector '512env.iv') with built-in user #1 private key, built-in user #2 public key. Outputs result to '512env.out' - read to verify. '767test.in' and '1024test.in' Same as '508test.in', except that '508' becomes '767' or '1024'. 'md2test.in' Verifies signature '512sig.md2' on 'signfile' with built-in user #1 public key. Run RDEMO with the '-2' flag for this script. " are programs which incorporate all or any portion of the Program in any form. The restrictions imposed on Arsaref/doc/install.txt1006440006630000000000000135005154544144012227 037777703401 1 0 To build RSAREF, copy the makefile for your operating system from the 'install' subdirectory to the 'test' subdirectory. Then run your operating system's 'make' program from the 'test' subdirectory. The makefile will compile the RSAREF source code and build the demonstration program. Makefiles are found in subdirectories of the 'install' subdirectory: dos Personal Computer running DOS, Microsoft C v6.00a mac Macintosh running System 7, MPW 3.2 unix NeXTStation, DECStation 3100, SPARCStation 1 vax MicroVAX II running VMS For example, suppose you are running DOS with Microsoft's NMAKE utility. From the 'test' directory you would run the commands: copy ..\install\dos\makefile nmake able requests for permission to make such modifications. 3. NO RSA OBLIGATION. You are solely responsible for all of your costs and expenses incurred in connection with the distribution of the Program or any Application Program hereunder, and RSA shallrsaref/doc/rsaref.txt1006440006630000000000007337505154544124012061 037777703401 1 0 RSAREF(TM): A Cryptographic Toolkit for Privacy-Enhanced Mail Library Reference Manual RSA Laboratories March 2, 1992 Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. INTRODUCTION This manual is a reference guide for users of RSAREF, a cryptographic toolkit designed to facilitate rapid development of Internet Privacy-Enhanced Mail (PEM) [1-3] implementations. RSAREF supports the following PEM-specified algorithms: - RSA encryption and key generation, as defined by RSA Data Security's Public-Key Cryptography Standards (PKCS) [4] - MD2 and MD5 message digests [3,5,6] - DES (Data Encryption Standard) in cipher-block chaining mode [7,8] RSAREF is written entirely in C. Its application interface includes the following routines: R_SignPEMBlock computes a digital signature on a message R_VerifyPEMSignature verifies a digital signature on a message R_VerifyBlockSignature verifies a digital signature on a block of data such as a certificate R_SealPEMBlock computes a digital signature and encrypts a message R_OpenPEMBlock decrypts an encrypted message and verifies a digital signature R_DigestBlock computes a message digest on a message R_GeneratePEMKeys generates an RSA public/private key pair R_RandomInit initializes a random structure R_RandomUpdate mixes bytes into a random structure R_GetRandomBytesNeeded computes the number of mix-in bytes still needed to seed a random structure R_RandomFinal zeroizes a random structure A simple PEM implementation can be built directly on top of these routines, together with message parsing and formatting routines and certificate-management routines. This manual is divided into five main parts and three appendices. This part introduces RSAREF. The next three parts explain RSAREF procedures: random structures; cryptographic enhancements; and key-pair generation. The last part documents the platform-specific run-time library. Appendix A lists RSAREF error types. Appendix B lists RSAREF types and constants. Appendix C lists platform-specific types and constants. RSAREF is intended to be compatible with forthcoming revised versions of the PEM RFCs, which are now in the unofficial "Internet-Draft" stage. RANDOM STRUCTURES A random structure contains a seed from which a pseudorandom sequence of bytes is derived. RSAREF generates keys and pads RSA encryption blocks with bytes derived from a random structure. Random structures are used by both message-processing and key-generation applications. RSAREF initializes a random structure with the procedure R_RandomInit. A typical application calls R_RandomInit on entry. A new random structure is not ready for use until it is seeded by mixing in some random bytes. RSAREF seeds a random structure with the procedure R_RandomUpdate and R_GetRandomBytesNeeded. A random structure is considered seeded when the number of bytes still needed reaches zero. More bytes can be mixed in after the random structure is seeded. A typical application calls R_GetRandomBytesNeeded and R_RandomUpdate immediately after calling R_RandomInit. RSAREF zeroizes a random structure with the procedure R_RandomFinal. A typical application calls R_RandomFinal on exit. R_RandomInit int R_RandomInit ( R_RANDOM_STRUCT *randomStruct /* new random structure */ ); R_RandomInit initializes a new random structure, storing the result in randomStruct. Return value: 0 success nonzero reserved for future compatibility R_RandomUpdate int R_RandomUpdate ( R_RANDOM_STRUCT *randomStruct, /* random structure */ unsigned char *block, /* block of values to mix in */ unsigned int blockLen /* length of block */ ); R_RandomUpdate mixes blockLen bytes from block into randomStruct. Return value: 0 success nonzero reserved for future compatibility R_GetRandomBytesNeeded int R_GetRandomBytesNeeded ( unsigned int *bytesNeeded, /* number of mix-in bytes needed */ R_RANDOM_STRUCT *randomStruct /* random structure */ ); R_GetRandomBytesNeeded computes the number of mix-in bytes still needed to seed randomStruct, storing the result in bytesNeeded. Return value: 0 success nonzero reserved for future compatibility R_RandomFinal void R_RandomFinal ( R_RANDOM_STRUCT *randomStruct /* random structure */ ); R_RandomFinal zeroizes randomStruct. No return value. CRYPTOGRAPHIC ENHANCEMENTS RSAREF applies cryptographic enhancements to messages with six procedures: R_SignPEMBlock, R_VerifyPEMSignature, R_VerifyBlockSignature, R_SealPEMBlock, R_OpenPEMBlock, and R_DigestBlock. The first five procedures are typically called by message-processing applications. R_DigestBlock is typically called by key-generation applications when computing the message digest of a prototype certificate [2,9]. To sign a message, an application calls R_SignPEMBlock, giving these arguments: - a pointer to the message content, and the message length - an integer identifying which message-digest algorithm to apply (MD2 or MD5) - a flag indicating whether to encode the message in printable ASCII according to RFC 1113 - the signer's RSA private key R_SignPEMBlock signs the message with the signer's private key and the specified message-digest algorithm, and optionally encodes the message in printable ASCII. It returns the signature, possibly the encoded message, and the status of the operation. The signature is encoded according to RFC 1113. To verify a signature on a message, an application calls R_VerifyPEMSignature, giving these arguments: - a pointer to the (possibly encoded) message, and the message length - a pointer to the signature, and the signature length - an integer identifying which message-digest algorithm was applied (MD2 or MD5) - a flag indicating whether the message was encoded in printable ASCII - the signer's RSA public key R_VerifyPEMSignature decodes the message if it was encoded and verifies the signature on the message with the signer's public key and the specified message-digest algorithm. It returns the message content if the message was encoded, and the status of the operation. To verify a signature on a block of data such as a certificate where the signature is not encoded in printable ASCII, an application calls R_VerifyBlockSignature, giving these arguments: - a pointer to the block, and the block length - a pointer to the signature, and the signature length - an integer identifying which message-digest algorithm was applied (MD2 or MD5) - the signer's RSA public key R_VerifyBlockSignature verifies the signature on the message with the signer's public key and the specified message-digest algorithm. It returns the status of the operation. To seal a message (sign and encrypt it), an application calls R_SealPEMBlock, giving these arguments: - a pointer to the message content, and the message length - an integer identifying which message-digest algorithm to apply (MD2 or MD5) - the signer's RSA private key - the recipient's RSA public key R_SealPEMBlock signs the message with the signer's private key and the specified message-digest algorithm, encrypts the message and the signature with a random DES key, and encrypts the DES key with the recipient's public key. It returns the encrypted message, the encrypted key, the encrypted signature, the DES initialization vector, and the status of the operation. The encrypted message, key, and signature are encoded according to RFC 1113. To open a message (decrypt it and verify its signature), an application calls R_OpenPEMBlock, giving these arguments: - a pointer to the encrypted message, and the encrypted message length - a pointer to the encrypted key, and the encrypted key length - a pointer to the encrypted signature, and the encrypted signature length - a DES initialization vector - an integer identifying which message-digest algorithm was applied (MD2 or MD5) - the signer's RSA public key - the recipient's RSA private key R_OpenPEMBlock decrypts the encrypted DES key with the recipient's private key, decrypts the encrypted message and the encrypted signature with the DES key, and verifies the signature on the message with the signer's public key and the specified message-digest algorithm. It returns the message content and the status of the operation. To digest a block of data such as a prototype certificate, an application calls R_DigestBlock, giving these arguments: - a pointer to the block, and the block length - an integer identifying which message-digest algorithm to apply (MD2 or MD5) R_DigestBlock digests the block with the specified message-digest algorithm. It returns the message digest and the status of the operation. ENCODED_CONTENT_LEN, DECODED_CONTENT_LEN, ENCRYPTED_CONTENT_LEN, and DECRYPTED_CONTENT_LEN are macros that assist in determining the maximum lengths of the results of cryptographic enhancements. R_SignPEMBlock int R_SignPEMBlock ( unsigned char *encodedContent, /* encoded content */ unsigned int *encodedContentLen, /* length of encoded content */ unsigned char *encodedSignature, /* encoded signature */ unsigned int *encodedSignatureLen, /* length of encoded signature */ unsigned char *content, /* content */ unsigned int contentLen, /* length of content */ int recode, /* recoding flag */ int digestAlgorithm, /* message-digest algorithm */ R_RSA_PRIVATE_KEY *privateKey /* signer's RSA private key */ ); R_SignPEMBlock computes a digital signature on content. Specifically, R_SignPEMBlock performs the following steps: 1. It digests content with digestAlgorithm, giving a message digest. 2. It encrypts the message digest with privateKey, giving a digital signature, and encodes the result in printable ASCII according to RFC 1113, storing the encoding in encodedSignature. 3. If recode is nonzero, it encodes content in printable ASCII, storing the encoding in encodedContent. If recode is nonzero, encodedContent will be an ASCII string, encoded according to RFC 1113. (It will not contain any line delimiters; the application must break the string into 64-character lines.) encodedContentLen will not be greater than ENCODED_CONTENT_LEN(contentLen). If recode is zero, encodedContent is ignored. encodedSignature will be an ASCII string, encoded according to RFC 1113. encodedSignatureLen will not be greater than MAX_PEM_SIGNATURE_LEN. digestAlgorithm is the algorithm by which the content is digested. It must be DA_MD2, which indicates the MD2 message-digest algorithm, or DA_MD5, which indicates the MD5 message-digest algorithm. Return value: 0 success RE_DIGEST_ALGORITHM digestAlgorithm is invalid RE_PRIVATE_KEY privateKey cannot encrypt message digest R_VerifyPEMSignature int R_VerifyPEMSignature ( unsigned char *content, /* content */ unsigned int *contentLen, /* length of content */ unsigned char *encodedContent, /* (possibly) encoded content */ unsigned int encodedContentLen, /* length of encoded content */ unsigned char *encodedSignature, /* encoded signature */ unsigned int encodedSignatureLen, /* length of encoded signature */ int recode, /* recoding flag */ int digestAlgorithm, /* message-digest algorithm */ R_RSA_PUBLIC_KEY *publicKey /* signer's RSA public key */ ); R_VerifyPEMSignature verifies a digital signature on a message. Its operation is the inverse of R_SignPEMBlock. R_VerifyPEMSignature operates on encodedSignature and encodedContent. If recode is nonzero, it first decodes encodedContent according to RFC 1113, and stores the result in content. If recode is zero, content is ignored. If recode is nonzero, contentLen will not be greater than DECODED_CONTENT_LEN(encodedContentLen). Return value: 0 success RE_CONTENT_ENCODING encodedContent has RFC 1113 encoding error RE_SIGNATURE_ENCODING encodedSignature has RFC 1113 encoding error RE_DIGEST_ALGORITHM digestAlgorithm is invalid RE_PUBLIC_KEY publicKey cannot decrypt signature RE_SIGNATURE signature on content is incorrect R_VerifyBlockSignature int R_VerifyBlockSignature ( unsigned char *block, /* block */ unsigned int blockLen, /* length of block */ unsigned char *signature, /* signature */ unsigned int signatureLen, /* length of signature */ int digestAlgorithm, /* message-digest algorithm */ R_RSA_PUBLIC_KEY *publicKey /* signer's RSA public key */ ); R_VerifyBlockSignature verifies a digital signature on a block of data such as a certificate. Its operation is similar to R_VerifyPEMSignature, except that the block and signature are arbitrary byte strings, rather than RFC 1113-encoded strings. Return value: 0 success RE_DIGEST_ALGORITHM digestAlgorithm is invalid RE_PUBLIC_KEY publicKey cannot decrypt signature RE_SIGNATURE signature on block is incorrect R_SealPEMBlock int R_SealPEMBlock ( unsigned char *encryptedContent, /* encoded, encrypted content */ unsigned int *encryptedContentLen, /* length of encoded, encrypted content */ unsigned char *encryptedKey, /* encoded, encrypted DES key */ unsigned int *encryptedKeyLen, /* length of encoded, encrypted DES key */ unsigned char *encryptedSignature,/* encoded, encrypted signature */ unsigned int *encryptedSignatureLen, /* length of encoded, encrypted signature */ unsigned char iv[8], /* DES initializing vector */ unsigned char *content, /* content */ unsigned int contentLen, /* length of content */ int digestAlgorithm, /* message-digest algorithm */ R_RSA_PUBLIC_KEY *publicKey, /* recipient's RSA public key */ R_RSA_PRIVATE_KEY *privateKey, /* signer's RSA private key */ R_RANDOM_STRUCT *randomStruct /* random structure */ ); R_SealPEMBlock computes a digital signature on content then encrypts the content and the signature. Specifically, R_SealPEMBlock performs the following steps: 1. It digests content with digestAlgorithm, giving a message digest. 2. It encrypts the message digest with privateKey, giving a digital signature. 3. It generates a random DES key and initializing vector, storing the initializing vector in iv. 4. It encrypts content with the DES key and initializing vector in cipher-block chaining mode, and encodes the result in printable ASCII according to RFC 1113, storing the encoding in encryptedContent. 5. It encrypts the DES key with publicKey and encodes the result in printable ASCII, storing the encoding in encryptedKey. 6. It encrypts the digital signature with the DES key and initializing vector, and encodes the result in printable ASCII, storing the encoding in encryptedSignature. encryptedContent will be an ASCII string, encoded according to RFC 1113. (It will not contain any line delimiters; the application must break the string into 64-character lines.) encryptedContentLen will not be greater than ENCRYPTED_CONTENT_LEN(contentLen). encryptedKey and encryptedSignature will be ASCII strings, encoded according to RFC 1113. encryptedKeyLen will not be greater than MAX_PEM_ENCRYPTED_KEY_LEN. encryptedSignatureLen will not be greater than MAX_PEM_ENCRYPTED_SIGNATURE_LEN. digestAlgorithm is the algorithm by which the content is digested. It must be DA_MD2, which indicates the MD2 message-digest algorithm, or DA_MD5, which indicates the MD5 message-digest algorithm. randomStruct must have been seeded. Return value: 0 success RE_DIGEST_ALGORITHM digestAlgorithm is invalid RE_PRIVATE_KEY privateKey cannot encrypt message digest RE_PUBLIC_KEY publicKey cannot encrypt DES key RE_NEED_RANDOM randomStruct is not seeded R_OpenPEMBlock int R_OpenPEMBlock ( unsigned char *content, /* content */ unsigned int *contentLen, /* length of content */ unsigned char *encryptedContent, /* encoded, encrypted content */ unsigned int encryptedContentLen, /* length of encoded, encrypted content */ unsigned char *encryptedKey, /* encoded, encrypted DES key */ unsigned int encryptedKeyLen, /* length of encoded, encrypted DES key */ unsigned char *encryptedSignature,/* encoded, encrypted signature */ unsigned int encryptedSignatureLen, /* length of encoded, encrypted signature */ unsigned char iv[8], /* DES initializing vector */ int digestAlgorithm, /* message-digest algorithm */ R_RSA_PRIVATE_KEY *privateKey, /* recipient's RSA private key */ R_RSA_PUBLIC_KEY *publicKey /* signer's RSA public key */ ); R_OpenPEMBlock decrypts an encrypted message and verifies a digital signature. Its operation is the inverse of R_SealPEMBlock. contentLen will not be greater than DECRYPTED_CONTENT_LEN(encryptedContentLen). Return value: 0 success RE_CONTENT_ENCODING encryptedContent has RFC 1113 encoding error RE_KEY_ENCODING encryptedKey has RFC 1113 encoding error RE_SIGNATURE_ENCODING encryptedSignature has RFC 1113 encoding error RE_PUBLIC_KEY publicKey cannot decrypt signature RE_PRIVATE_KEY privateKey cannot decrypt encrypted key RE_KEY recovered DES key cannot decrypt encrypted content or encrypted signature RE_DIGEST_ALGORITHM digestAlgorithm is invalid RE_SIGNATURE signature on content is incorrect R_DigestBlock int R_DigestBlock ( unsigned char *digest, /* message digest */ unsigned int *digestLen, /* length of message digest */ unsigned char *content, /* content */ unsigned int contentLen, /* length of content */ int digestAlgorithm /* message-digest algorithm */ ); R_DigestBlock computes a message digest on content, storing the resulting message digest in digest and its length in digestLen. digestAlgorithm is the algorithm by which the content is digested. It must be DA_MD2, which indicates the MD2 message-digest algorithm, or DA_MD5, which indicates the MD5 message-digest algorithm. digestLen will not be greater than MAX_DIGEST_LEN. Return value: 0 success RE_DIGEST_ALGORITHM digestAlgorithm is invalid KEY-PAIR GENERATION RSAREF generates key pairs with the procedure R_GeneratePEMKeys. R_GeneratePEMKeys is typically called by key generation applications. To generate a new key pair, an application calls R_GeneratePEMKeys, giving the length of the modulus, the choice of exponent (F4 or F0), and a random structure. R_GeneratePEMKeys generates an RSA key pair and returns the status of the operation. R_GeneratePEMKeys int R_GeneratePEMKeys ( 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 */ ); R_GeneratePEMKeys generates a random RSA key pair, storing the resulting RSA public key in publicKey and the resulting RSA private key in privateKey. Other parameters are as follows: protoKey The RSA prototype key specifying the length in bits of the RSA modulus and the public exponent. (See Appendix B.) randomStruct Random structure from which the key pair is derived. It must have been seeded. Return value: 0 success RE_MODULUS_LEN modulus length invalid RE_NEED_RANDOM randomStruct is not seeded RUN-TIME LIBRARY RSAREF operates on memory blocks with three platform-specific library procedures that are modeled after conventional C library functions: R_memcmp compares two blocks of memory R_memcpy copies a block of memory R_memset sets a block of memory to a given value These procedures can be found in the file 'r_stdlib.c'. R_memcmp int R_memcmp ( POINTER firstBlock, /* first block */ POINTER secondBlock, /* second block */ unsigned int len /* length of blocks */ ); R_memcmp compares the first len bytes of firstBlock and secondBlock. The value of len can be zero, in which case firstBlock and secondBlock are undefined and R_memcmp returns 0. R_memcmp compares the blocks by scanning the blocks from lowest address to highest until a difference is found. The smaller-valued block is the one with the smaller-valued byte at the point of difference. If no difference is found, the blocks are equal. Return value: < 0 firstBlock is smaller 0 blocks are equal > 0 firstBlock is larger R_memcpy void R_memcpy ( POINTER output, /* output block */ POINTER input, /* input block */ unsigned int len /* length of blocks */ ); R_memcpy copies the first len bytes of input to output. The value of len can be zero, in which output and input are undefined. The blocks do not overlap. No return value. R_memset void R_memset ( POINTER output, /* output block */ int value, /* value */ unsigned int len /* length of block */ ); R_memset sets the first len bytes of output to value. The value of len is zero, in which case output is undefined. No return value. APPENDIX A: RSAREF ERROR TYPES This appendix lists RSAREF's error types. RE_CONTENT_ENCODING content or encrypted content has RFC 1113 encoding error RE_DIGEST_ALGORITHM message-digest algorithm is invalid RE_KEY recovered DES key cannot decrypt encrypted content or encrypted signature RE_KEY_ENCODING encrypted key has RFC 1113 encoding error RE_MODULUS_LEN modulus length is invalid RE_NEED_RANDOM random structure is not seeded RE_PRIVATE_KEY private key cannot encrypt message digest, or cannot decrypt encrypted key RE_PUBLIC_KEY public key cannot encrypt DES key, or cannot decrypt signature RE_SIGNATURE signature on content or block is incorrect RE_SIGNATURE_ENCODING signature or encrypted signature has RFC 1113 encoding error APPENDIX B: RSAREF TYPES This appendix lists three RSAREF types: R_RSA_PUBLIC_KEY, R_RSA_PRIVATE_KEY, and R_RSA_PROTO_KEY. 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; An R_RSA_PUBLIC_KEY value is a structure specifying an RSA public key. There are three fields: bits length in bits of the modulus (not less than MIN_RSA_MODULUS_BITS and not greater than MAX_RSA_MODULUS_BITS) modulus modulus n, represented as a MAX_RSA_MODULUS_LEN-byte number, most significant byte first, as many leading zero bytes as necessary exponent public exponent e, represented like 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; An R_RSA_PRIVATE_KEY value is a structure specifying an RSA private key. There are seven fields: bits length in bits of the modulus (not less than MIN_RSA_MODULUS_BITS and not greater than MAX_RSA_MODULUS_BITS) modulus modulus n, represented as a MAX_RSA_MODULUS_LEN-byte number, most significant byte first, as many leading zero bytes as necessary publicExponent public exponent e, represented like modulus exponent private exponent d, represented like modulus prime prime factors p and q of modulus, each represented as MAX_RSA_PRIME_LEN-byte numbers, most significant byte first, as many leading zero bytes as necessary, where p > q primeExponents exponents (d mod p-1) and (d mod q-1) for Chinese remainder theorem (CRT) operations, each represented like prime factors coefficient coefficient (q^{-1} mod p) for Chinese remainder theorem operations, represented like prime factors R_RSA_PROTO_KEY /* RSA prototype key. */ typedef struct { unsigned int bits; /* length in bits of modulus */ int useFermat4; /* public exponent (1 = F4, 0 = 3) */ } R_RSA_PROTO_KEY; An R_RSA_PROTO_KEY value is a structure specifying the length in bits of the RSA modulus and the public exponent for key-pair generation. There are two fields: bits length in bits of the modulus (not less than MIN_RSA_MODULUS_BITS and not greater than MAX_RSA_MODULUS_BITS) useFermat4 a flag specifying the public exponent. If nonzero, it specifies F4 (65537); if 0, F0 (3) APPENDIX C: PLATFORM-SPECIFIC TYPES AND CONSTANTS This appendix lists three platform-specific types and one #define'd constant. TYPES RSAREF requires three platform-specific types: POINTER, UINT2, and UINT4. These are defined in the file 'global.h'. POINTER A POINTER value is a generic pointer to memory to which any other pointer can be cast. Example: typedef unsigned char *POINTER; UINT2 A UINT2 value is a 16-bit unsigned integer. Example: typedef unsigned short int UINT2; UINT4 A UINT4 value is a 32-bit unsigned integer. Example: typedef unsigned long int UINT4; #DEFINE'D CONSTANTS RSAREF requires one #define'd constant: PROTOTYPES. This is defined in the 'makefile' on the C compiler command line. PROTOTYPES indicates the form that C function declarations are to take. If PROTOTYPES is nonzero, declarations take the form type function (type, ..., type); Otherwise declarations take the form type function (); REFERENCES [1] J. Linn. RFC 1113: Privacy Enhancement for Internet Electronic Mail: Part I -- Message Encipherment and Authentication Procedures. Internet Activities Board, August 1989. [2] S. Kent and J. Linn. RFC 1114: Privacy Enhancement for Internet Electronic Mail: Part II -- Certificate-Based Key Management. Internet Activities Board, August 1989. [3] J. Linn. RFC 1115: Privacy Enhancement for Internet Electronic Mail: Part III -- Algorithms, Modes, and Identifiers. Internet Activities Board, August 1989. [4] RSA Data Security, Inc. PKCS #1: RSA Encryption Standard. Version 1.4, June 1991. Also published as NIST/OSI Implementors Workshop SEC-SIG-91-18, June 1991. (Available by anonymous FTP from 'rsa.com' as 'pub/pkcs/pkcs-1.ps'.) [5] B.S. Kaliski Jr. The MD2 Message-Digest Algorithm. July 1, 1991. (Available by anonymous FTP from 'rsa.com' as 'pub/md2.doc'.) [6] Ronald L. Rivest. The MD5 Message-Digest Algorithm. In preparation. (Earlier version available by anonymous FTP from 'rsa.com' as 'pub/md5.doc'.) [7] National Bureau of Standards. FIPS Publication 46-1: Data Encryption Standard. January 1988. [8] National Bureau of Standards. FIPS Publication 81: DES Modes of Operation. December 1980. [9] B.S. Kaliski Jr. Privacy Enhancement for Internet Electronic Mail: Part IV: Notary, Co-Issuer, CRL-Storing, and CRL-Retrieving Services. Draft, July 1, 1991. (Available by anonymous FTP from 'rsa.com' as 'pub/forms.doc'.) the status of the operation. R_GeneratePEMKeys int R_GeneratePEMKeys ( R_RSA_PUBLIC_KEY *publicKey, /* new RSA public key */ R_RSA_PRIVATE_KEY *privateKey, /* new RSA private key */ R_RSA_PROTO_KEY *protoKey, rsaref/doc/rdemo.txt1006440006630000000000001135505326645507011703 037777703401 1 0 RDEMO: Demonstration program for RSAREF User's manual RSA Laboratories March 2, 1992 Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. This note describes RDEMO, a demonstration program included with the RSAREF cryptographic toolkit. RDEMO is a simple program that exercises RSAREF's cryptographic operations. With RDEMO three "users" can perform the cryptographic operations of signing, sealing, verifying, and opening files, as well as generating key pairs. RDEMO has a main menu with six commands. The main menu is displayed when you start up RDEMO, and is displayed again after RDEMO performs a command. After you select a command RDEMO prompts for parameters such as file names. RDEMO's commands and their parameters are summarized in the following table. RDEMO COMMAND PARAMETERS S - Sign a file name of file sign contents with private whether you want content encoded key which user you want to sign as optionally encode contents name of file in which to save in PEM character set(*) signature name of file in which to save encoded content(**) E - sEal a file name of file sign contents with private which user you want to sign as key which user you want to seal for generate random DES key names of four files in which to save IV(***) encrypted signature, encrypted key, encrypt content, signature IV and encrypted content with DES key V - Verify a signed file whether content is encoded decode contents if encoded names of two files in which (possibly in PEM character set encoded) content and signature are verify signature on saved contents with public key which user signed the file name of file in which to save recovered content(**) O - Open a sealed file names of four files in which encrypted decrypt encrypted DES key content, encrypted signature, with private key, encrypted key and IV are saved decrypt encrypted content which user signed the file signature with DES key which user the file was sealed for verify signature on name of file in which to save contents with public key recovered content G - Generate a keypair length of key in bits (508-1024) generate RSA public/ name of file in which to save key pair private key pair Q - Quit (*) A 65-character subset of ASCII defined in RFC 1113. Most other quantities are encoded in this set automatically. (**) Only if content is encoded. (***) Initialization vector for cipher-block chaining mode of DES. NOTES 1. You select a user by number: '1', '2', or '3'. The first two users have built-in RSA key pairs. The third user's key pair is the one generated by RDEMO's 'Generate a key pair' command. The third user is not active until the key pair is generated. 2. How you specify file names to RDEMO depends on your operating system. RDEMO recognizes the special file name '-' as the standard output stream (typically the screen display). You can usually cancel an RDEMO command by giving a blank line in response to a prompt for a parameter. 3. RDEMO reads most files and writes all files in binary mode. The only exceptions are the files containing contents to be signed or sealed. Those files are read in text mode, one line at a time, with RDEMO replacing any and delimiters with a pair before encrypting, computing a message digest, or encoding in printable ASCII. The processing compensates for differences in line delimiters in different operating systems. RDEMO has a maximum file size of 1000 bytes. 4. RDEMO defaults to the MD5 message-digest algorithm for all signatures. If you want the MD2 message-digest algorithm, put the string '-2' on the command line when you start RDEMO. 5. If you want RDEMO not to display the main menu or any prompts, put the string '-s' on the command line when you start RDEMO. This is useful when RDEMO's input stream comes from a script file. 6. RDEMO seeds RSAREF's random number generator with a fixed value. As a result, RDEMO sessions with the same commands and parameters produce the same results. The use of a fixed seed value is not recommended for non-demonstration applications. PRIVATE_KEY; An R_RSA_PRIVATE_KEY value is a structure specifying an RSA private key. There are seven fields: bits length in bits of the modulus (not less than MIN_RSA_MODULUS_BITS and not greater than rsaref/install/0407750006630000000000000000005626264725010161 5 0 1 0 rsaref/install/dos/0407750006630000000000000000005626264722010743 5 0 1 0 rsaref/install/dos/makefile1006440006630000000000000232005570201323013173 037777703401 1 0 # This is a MAKEFILE for Microsoft's NMAKE # extension for object files O = obj # commands CC = cl LIB = lib ASM = masm # name of temporary library script TEMPFILE = $(TEMP)\temp.mak # standard include directory STDINCDIR = i:\msc6\include # The places to look for include files (in order). INCL = -I. -I$(SRCDIR) -I$(STDINCDIR) # Normal C flags. CFLAGS = -W3 -AL -Zp $(INCL) -c -DPROTOTYPES=1 -DUSEMPILIB LFLAGS = /stack:26000 # Debugging C flags. #CFLAGS = -W3 -AL -Zpi -Od $(INCL) -c -DPROTOTYPES=1 #LFLAGS = /codeview /map /stack:26000 # The location of the common source directory. SRCDIR = ..\source\# SRCLIB = rsaref.lib # The location of the demo source directory. RDEMODIR = ..\rdemo\# all : $(SRCLIB) rdemo.exe : rdemo.$(O) $(SRCLIB) link @< $(TEMPFILE) @!echo -+$? & >> $(TEMPFILE) @echo ;' >> $(TEMPFILE) @$(LIB) @$(TEMPFILE) rdemo.$(O) : $(RDEMODIR)rdemo.c global.h $(SRCDIR)rsaref.h $(CC) $(CFLAGS) $(RDEMODIR)rdemo.c !INCLUDE $(SRCDIR)targets.mak he form type function (); REFERENCES [1] J. Linn. RFC 1113: Privacy Enhancement for Internet Electronic Mail: Part I -- Message Encipherment and Authentication Procedures. Internet Activities Board, August 1989. [2] S. Kent and J. Linn. RFC 1114: Privacy Enhancement for Internet rsaref/install/unix/0407750006630000000000000000005632461371011135 5 0 1 0 rsaref/install/unix/makefile1006440006630000000000000304705632461326013412 037777703401 1 0 # This is a makefile for UNIX # CHANGES MADE TO THIS FILE UNDER RSAREF license clause 1(c): # # For the MIT PGP 2.6 distribution, this file was modified to permit # replacement of the NN_ModExp routine by an equivalent routine # contained in the PGP 2.6 sources. To enable this change, an #ifdef # was added to the nn.c file (search for #ifndef USEMPILIB # below). RSAREF *must* be compiled with USEMPILIB defined for this # change to occur. # # This makefile was changed to use GCC and to define USEMPILIB # Change made May 21, 1994. # # extension for object files O = o # commands CC = gcc RANLIB = ranlib LIB = ar ASM = masm PROTOTYPES = 1 # name of temporary library script TEMPFILE = $(TEMP)/temp.mak # standard include directory STDINCDIR=/usr/include # The places to look for include files (in order). INCL = -I. -I$(SRCDIR) -I$(STDINCDIR) # name of main executable to build PROG = rdemo # Normal GCC flags. CFLAGS = $(INCL) -O -c -DPROTOTYPES=$(PROTOTYPES) -DUSEMPILIB MFLAGS = -I. -I$(SRCDIR) # The location of the common source directory. SRCDIR = ../../source/ SRCLIB = rsaref.a # The location of the demo source directory. RDEMODIR = ../../rdemo/ all : $(SRCLIB) rdemo : rdemo.$(O) $(SRCLIB) $(CC) -o $@ rdemo.$(O) $(SRCLIB) $(SRCLIB) : desc.$(O) digit.$(O) md2c.$(O) md5c.$(O) nn.$(O) prime.$(O)\ rsa.$(O) r_encode.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O)\ r_stdlib.$(O) $(LIB) r $@ $? $(RANLIB) $@ rdemo.$(O) : $(RDEMODIR)rdemo.c global.h $(SRCDIR)rsaref.h $(CC) $(CFLAGS) $(RDEMODIR)rdemo.c include $(SRCDIR)targets.mak yptographic operations of signing, sealing, verifying, and opening files, as well as generating key pairs. RDEMO has a main menu with six commands. The main menu is displayed when you start up RDEMO, and is displayed again after RDEMO performs a command. After you select a command RDEMO prompts for parameters such as file names. RDEMO's commands and their parameters are summarized in the following table. RDEMO COMMAND PARAMETERS S -rsaref/install/unix/global.h1004440006630000000000000235405602141121013302 037777703401 1 0 /* GLOBAL.H - RSAREF types and constants */ /**************************************************************** NOTE: This copy has been modified for compilation on DEC OSF/1 on Alpha AXP. See the definition of UINT4 below. John Kohl, , 1994/June/16 ****************************************************************/ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ /* PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping. The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 #endif /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ #ifdef __alpha typedef unsigned int UINT4; #else typedef unsigned long int UINT4; #endif /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif e key pair private key pair Q - Quit (*) A 65-character subset of ASCII defined in RFC 1113. Most other quantities are encoded in this set automatically. (**) Only if content is encoded. (***) Initialization vector for cipher-block chaining mode of DES. NOTES rsaref/install/mac/0407750006630000000000000000005632677245010723 5 0 1 0 rsaref/install/mac/rdemo.mak1004440006630000000000000714005632677240013267 037777703401 1 0 # File: rsaref.make # Target: rsaref # Sources: "{rsarefdir}"SOURCE:DESC.C # "{rsarefdir}"SOURCE:DIGIT.C # "{rsarefdir}"SOURCE:MD2C.C # "{rsarefdir}"SOURCE:MD5C.C # "{rsarefdir}"SOURCE:NN.C # "{rsarefdir}"SOURCE:PRIME.C # "{rsarefdir}"SOURCE:RSA.C # "{rsarefdir}"SOURCE:R_ENCODE.C # "{rsarefdir}"SOURCE:R_ENHANC.C # "{rsarefdir}"SOURCE:R_KEYGEN.C # "{rsarefdir}"SOURCE:R_RANDOM.C # "{rsarefdir}"SOURCE:R_STDLIB.C # Created: Tuesday, February 25, 1992 5:12:56 PM # Variable for user to specify the installed location. # # This should be set to the folder that contains the folders SOURCE,RDEMO,TEST... # rsarefdir = {Boot}RSAREF: objects = "{rsarefdir}"SOURCE:DESC.C.o ¶ "{rsarefdir}"SOURCE:DIGIT.C.o ¶ "{rsarefdir}"SOURCE:MD2C.C.o ¶ "{rsarefdir}"SOURCE:MD5C.C.o ¶ "{rsarefdir}"SOURCE:NN.C.o ¶ "{rsarefdir}"SOURCE:PRIME.C.o ¶ "{rsarefdir}"SOURCE:RSA.C.o ¶ "{rsarefdir}"SOURCE:R_ENCODE.C.o ¶ "{rsarefdir}"SOURCE:R_ENHANC.C.o ¶ "{rsarefdir}"SOURCE:R_KEYGEN.C.o ¶ "{rsarefdir}"SOURCE:R_RANDOM.C.o ¶ "{rsarefdir}"SOURCE:R_STDLIB.C.o demoobjects = rsaref.o "{rsarefdir}"RDEMO:RDEMO.C.o rdemo ÄÄ {demoobjects} Link -d -c 'MPS ' -t MPST ¶ {demoobjects} ¶ #"{CLibraries}"CSANELib.o ¶ #"{CLibraries}"Math.o ¶ #"{CLibraries}"Complex.o ¶ "{CLibraries}"StdClib.o ¶ "{Libraries}"Stubs.o ¶ "{Libraries}"Runtime.o ¶ "{Libraries}"Interface.o ¶ #"{Libraries}"ToolLibs.o ¶ -o rdemo "{rsarefdir}"rdemo:RDEMO.C.o Ä rdemo.make "{rsarefdir}"rdemo:RDEMO.C C -r -i "{rsarefdir}"SOURCE: "{rsarefdir}"rdemo:RDEMO.C rsaref.o ÄÄ {objects} rdemo.make LIB -o RSAREF.o ¶ "{rsarefdir}"SOURCE:DESC.C.o ¶ "{rsarefdir}"SOURCE:DIGIT.C.o ¶ "{rsarefdir}"SOURCE:MD2C.C.o ¶ "{rsarefdir}"SOURCE:MD5C.C.o ¶ "{rsarefdir}"SOURCE:NN.C.o ¶ "{rsarefdir}"SOURCE:PRIME.C.o ¶ "{rsarefdir}"SOURCE:RSA.C.o ¶ "{rsarefdir}"SOURCE:R_ENCODE.C.o ¶ "{rsarefdir}"SOURCE:R_ENHANC.C.o ¶ "{rsarefdir}"SOURCE:R_KEYGEN.C.o ¶ "{rsarefdir}"SOURCE:R_RANDOM.C.o ¶ "{rsarefdir}"SOURCE:R_STDLIB.C.o "{rsarefdir}"SOURCE:DESC.C.o Ä rdemo.make "{rsarefdir}"SOURCE:DESC.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:DESC.C "{rsarefdir}"SOURCE:DIGIT.C.o Ä rdemo.make "{rsarefdir}"SOURCE:DIGIT.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:DIGIT.C "{rsarefdir}"SOURCE:MD2C.C.o Ä rdemo.make "{rsarefdir}"SOURCE:MD2C.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:MD2C.C "{rsarefdir}"SOURCE:MD5C.C.o Ä rdemo.make "{rsarefdir}"SOURCE:MD5C.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:MD5C.C "{rsarefdir}"SOURCE:NN.C.o Ä rdemo.make "{rsarefdir}"SOURCE:NN.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:NN.C "{rsarefdir}"SOURCE:PRIME.C.o Ä rdemo.make "{rsarefdir}"SOURCE:PRIME.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:PRIME.C "{rsarefdir}"SOURCE:RSA.C.o Ä rdemo.make "{rsarefdir}"SOURCE:RSA.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:RSA.C "{rsarefdir}"SOURCE:R_ENCODE.C.o Ä rdemo.make "{rsarefdir}"SOURCE:R_ENCODE.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:R_ENCODE.C "{rsarefdir}"SOURCE:R_ENHANC.C.o Ä rdemo.make "{rsarefdir}"SOURCE:R_ENHANC.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:R_ENHANC.C "{rsarefdir}"SOURCE:R_KEYGEN.C.o Ä rdemo.make "{rsarefdir}"SOURCE:R_KEYGEN.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:R_KEYGEN.C "{rsarefdir}"SOURCE:R_RANDOM.C.o Ä rdemo.make "{rsarefdir}"SOURCE:R_RANDOM.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:R_RANDOM.C "{rsarefdir}"SOURCE:R_STDLIB.C.o Ä rdemo.make "{rsarefdir}"SOURCE:R_STDLIB.C C -r -d PROTOTYPES=1 "{rsarefdir}"SOURCE:R_STDLIB.C (RDEMODIR)rdemo.c global.h $(SRCDIR)rsaref.h $(CC) $(CFLAGS) $(RDEMODIR)rdemo.c !INCLUDE $(SRCDIR)targets.mak he form type function (); REFERENCES [1] J. Linn. RFC 1113: Privacy Enhancement for Internet Electronic Mail: Part I -- Message Encipherment and Authentication Procedures. Internet Activities Board, August 1989. [2] S. Kent and J. Linn. RFC 1114: Privacy Enhancement for Internet rsaref/install/vax/0407750006630000000000000000005626264725010757 5 0 1 0 rsaref/install/vax/makefile1006440006630000000000000223005153737635013225 037777703401 1 0 ! This is a MAKEFILE for VAX MMS utility ! extension for object files O = obj ! commands CC = cc LIB = lib LINK = link ! The name for the demo exectuble. PROG = rdemo ! The location of the source code for the demo. RDEMODIR = DISK$USERS:[RSAREF.RDEMO] ! The location of the common source directory. SRCDIR = DISK$USERS:[RSAREF.SOURCE] SRCLIB = rsaref.olb ! The places to look for include files (in order). INCL = /INCLUDE_DIRECTORY=([],$(SRCDIR)) ! Normal C flags. CFLAGS = $(INCL)/NoDebug/Optimize/Obj=$(MMS$TARGET) LFLAGS = /Exec=$(MMS$TARGET)/NoTraceback/NoDebug ! Debugging C flags. ! CFLAGS = $(INCL)/Debug/NoOptimize/Obj=$(MMS$TARGET) ! LFLAGS = /Exec=$(MMS$TARGET)/Traceback/Debug/Map/Full/Cross $(PROG) : rdemo.$(O) $(SRCLIB) $(LINK) $(LFLAGS) rdemo.$(O),- $(SRCLIB)/Library all : $(SRCLIB) $(SRCLIB) : desc.$(O) digit.$(O) md2c.$(O) md5c.$(O) nn.$(O)\ prime.$(O) rsa.$(O) r_encode.$(O) r_enhanc.$(O) r_keygen.$(O)\ r_random.$(O) r_stdlib.$(O) $(LIB) /create $@ $(LIB) /replace $@ $? .INCLUDE $(SRCDIR)targets.mak rdemo.$(O) : $(RDEMODIR)rdemo.c global.h $(SRCDIR)rsaref.h $(CC) $(CFLAGS) $(RDEMODIR)rdemo.c mo/ all : $(SRCLIB) rdemo : rdemo.$(O) $(SRCLIB) $(CC) -o $@ rdemo.$(O) $(SRCLIB) $(SRCLIB) : desc.$(O) digit.$(O) md2c.$(O) md5c.$(O) nn.$(O) prime.$(O)\ rsa.$(O) r_encode.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O)\ r_stdlib.$(O) $(LIB) r $@ $? $(RANLIB) $@ rdemo.$(O) : $(RDEMODIR)rdemo.c global.h $(SRCDIR)rsaref.h $(CC) $(CFLAGS) $(RDEMODIRrsaref/rdemo/0407750006630000000000000000005626264725007621 5 0 1 0 rsaref/rdemo/rdemo.c1006440006630000000000010562405153737415011650 037777703401 1 0 /* RDEMO.C - RSAREF demonstration program */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include #include #include "global.h" #include "rsaref.h" int main PROTO_LIST ((int, char **)); static int SetOptions PROTO_LIST ((int, char **)); static void InitRandomStruct PROTO_LIST ((R_RANDOM_STRUCT *)); static void DoSignFile PROTO_LIST ((void)); static void DoSealFile PROTO_LIST ((R_RANDOM_STRUCT *)); static void DoVerifyFile PROTO_LIST ((void)); static void DoOpenFile PROTO_LIST ((void)); static void DoGenerateKeys PROTO_LIST ((R_RANDOM_STRUCT *)); static void WriteKeypair3 PROTO_LIST ((void)); static void WriteBigInteger PROTO_LIST ((FILE *, unsigned char *, unsigned int)); static int ReadBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned int, char *)); static int ReadText PROTO_LIST ((unsigned char *, unsigned int *, unsigned int, char *)); static int WriteBlock PROTO_LIST ((unsigned char *, unsigned int, char *)); static int GetPublicKey PROTO_LIST ((R_RSA_PUBLIC_KEY **, char *)); static int GetPrivateKey PROTO_LIST ((R_RSA_PRIVATE_KEY **, char *)); static void PrintMessage PROTO_LIST ((char *)); static void PrintError PROTO_LIST ((char *, int)); static void GetCommand PROTO_LIST ((char *, unsigned int, char *)); static int SILENT_PROMPT = 0; static int DIGEST_ALGORITHM = DA_MD5; static R_RSA_PUBLIC_KEY PUBLIC_KEY1 = { 512, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x76, 0x47, 0x97, 0xb8, 0xbe, 0xc8, 0x97, 0x2a, 0x0e, 0xd8, 0xc9, 0x0a, 0x8c, 0x33, 0x4d, 0xd0, 0x49, 0xad, 0xd0, 0x22, 0x2c, 0x09, 0xd2, 0x0b, 0xe0, 0xa7, 0x9e, 0x33, 0x89, 0x10, 0xbc, 0xae, 0x42, 0x20, 0x60, 0x90, 0x6a, 0xe0, 0x22, 0x1d, 0xe3, 0xf3, 0xfc, 0x74, 0x7c, 0xcf, 0x98, 0xae, 0xcc, 0x85, 0xd6, 0xed, 0xc5, 0x2d, 0x93, 0xd5, 0xb7, 0x39, 0x67, 0x76, 0x16, 0x05, 0x25}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01} }; static R_RSA_PRIVATE_KEY PRIVATE_KEY1 = { 512, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x76, 0x47, 0x97, 0xb8, 0xbe, 0xc8, 0x97, 0x2a, 0x0e, 0xd8, 0xc9, 0x0a, 0x8c, 0x33, 0x4d, 0xd0, 0x49, 0xad, 0xd0, 0x22, 0x2c, 0x09, 0xd2, 0x0b, 0xe0, 0xa7, 0x9e, 0x33, 0x89, 0x10, 0xbc, 0xae, 0x42, 0x20, 0x60, 0x90, 0x6a, 0xe0, 0x22, 0x1d, 0xe3, 0xf3, 0xfc, 0x74, 0x7c, 0xcf, 0x98, 0xae, 0xcc, 0x85, 0xd6, 0xed, 0xc5, 0x2d, 0x93, 0xd5, 0xb7, 0x39, 0x67, 0x76, 0x16, 0x05, 0x25}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xe3, 0x6b, 0x75, 0x22, 0xf6, 0x64, 0x87, 0xd9, 0xf4, 0x61, 0x0d, 0x15, 0x50, 0x29, 0x0a, 0xc2, 0x02, 0xc9, 0x29, 0xbe, 0xdc, 0x70, 0x32, 0xcc, 0x3e, 0x02, 0xac, 0xf3, 0x7e, 0x3e, 0xbc, 0x1f, 0x86, 0x6e, 0xe7, 0xef, 0x7a, 0x08, 0x68, 0xd2, 0x3a, 0xe2, 0xb1, 0x84, 0xc1, 0xab, 0xd6, 0xd4, 0xdb, 0x8e, 0xa9, 0xbe, 0xc0, 0x46, 0xbd, 0x82, 0x80, 0x37, 0x27, 0xf2, 0x88, 0x87, 0x01}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x02, 0xb6, 0x15, 0xfe, 0x15, 0x92, 0x8f, 0x41, 0xb0, 0x2b, 0x58, 0x6b, 0x51, 0xc2, 0xc0, 0x22, 0x60, 0xca, 0x39, 0x68, 0x18, 0xca, 0x4c, 0xba, 0x60, 0xbb, 0x89, 0x24, 0x65, 0xbe, 0x35}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xee, 0xb6, 0x0d, 0x54, 0x35, 0x18, 0xb4, 0xac, 0x74, 0x83, 0x4a, 0x05, 0x46, 0xc5, 0x07, 0xf2, 0xe9, 0x1e, 0x38, 0x9a, 0x87, 0xe2, 0xf2, 0xbe, 0xcc, 0x6f, 0x8c, 0x67, 0xd1, 0xc9, 0x31}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x48, 0x7e, 0x99, 0xe3, 0x75, 0xc3, 0x8d, 0x73, 0x21, 0x12, 0xd9, 0x7d, 0x6d, 0xe8, 0x68, 0x7f, 0xda, 0xfc, 0x5b, 0x6b, 0x5f, 0xb1, 0x6e, 0x72, 0x97, 0xd3, 0xbd, 0x1e, 0x43, 0x55, 0x99}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xb5, 0x50, 0xde, 0x64, 0x37, 0x77, 0x4d, 0xb0, 0x57, 0x77, 0x18, 0xed, 0x6c, 0x77, 0x07, 0x24, 0xee, 0xe4, 0x66, 0xb4, 0x31, 0x14, 0xb5, 0xb6, 0x9c, 0x43, 0x59, 0x1d, 0x31, 0x32, 0x81}}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x4c, 0x79, 0xc4, 0xb9, 0xbe, 0xa9, 0x7c, 0x25, 0xe5, 0x63, 0xc9, 0x40, 0x7a, 0x2d, 0x09, 0xb5, 0x73, 0x58, 0xaf, 0xe0, 0x9a, 0xf6, 0x7d, 0x71, 0xf8, 0x19, 0x8c, 0xb7, 0xc9, 0x56, 0xb8} }; static R_RSA_PUBLIC_KEY PUBLIC_KEY2 = { 512, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xf2, 0x0d, 0xce, 0x83, 0x32, 0x30, 0xe4, 0x51, 0xd5, 0x0c, 0x79, 0xa5, 0x34, 0x23, 0xfb, 0x5f, 0xfb, 0xa0, 0xff, 0x5c, 0x77, 0x96, 0xa9, 0x2c, 0x35, 0xee, 0x53, 0x02, 0xb7, 0x89, 0x2d, 0xf0, 0x78, 0x49, 0xdd, 0xdc, 0x27, 0x79, 0x8b, 0x69, 0xa2, 0x5e, 0x7a, 0x40, 0x27, 0x43, 0x82, 0x7a, 0xc4, 0xfa, 0x50, 0x21, 0x1f, 0x15, 0x35, 0xc3, 0x93, 0x46, 0x62, 0xcd, 0xd4, 0x26, 0x89}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01} }; static R_RSA_PRIVATE_KEY PRIVATE_KEY2 = { 512, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xf2, 0x0d, 0xce, 0x83, 0x32, 0x30, 0xe4, 0x51, 0xd5, 0x0c, 0x79, 0xa5, 0x34, 0x23, 0xfb, 0x5f, 0xfb, 0xa0, 0xff, 0x5c, 0x77, 0x96, 0xa9, 0x2c, 0x35, 0xee, 0x53, 0x02, 0xb7, 0x89, 0x2d, 0xf0, 0x78, 0x49, 0xdd, 0xdc, 0x27, 0x79, 0x8b, 0x69, 0xa2, 0x5e, 0x7a, 0x40, 0x27, 0x43, 0x82, 0x7a, 0xc4, 0xfa, 0x50, 0x21, 0x1f, 0x15, 0x35, 0xc3, 0x93, 0x46, 0x62, 0xcd, 0xd4, 0x26, 0x89}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x6b, 0x48, 0x4f, 0xe3, 0x04, 0x60, 0x31, 0xd9, 0xd9, 0x59, 0xdb, 0xb2, 0x0d, 0xc4, 0x47, 0x7a, 0x60, 0x70, 0x8c, 0x19, 0x2a, 0x5c, 0x9f, 0x35, 0x29, 0xc6, 0x0d, 0x95, 0xfe, 0x35, 0x30, 0x99, 0x54, 0xda, 0x99, 0x90, 0xe3, 0x3e, 0x1d, 0xdb, 0x32, 0x7b, 0x1d, 0x26, 0xf2, 0x9a, 0xab, 0x03, 0x09, 0x77, 0xba, 0x4f, 0x43, 0xdb, 0xda, 0xc8, 0x1f, 0x12, 0xd6, 0xf2, 0x57, 0x1a, 0x31}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x6c, 0x5d, 0xb7, 0x7b, 0xa7, 0x9e, 0x2f, 0x4a, 0x26, 0xec, 0xe0, 0x1b, 0x2a, 0x5f, 0x42, 0x04, 0x87, 0xb4, 0xc4, 0x68, 0x80, 0xf3, 0x09, 0xe5, 0x48, 0x00, 0x30, 0x6f, 0x54, 0x04, 0x75}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xd6, 0x25, 0x08, 0xe5, 0x54, 0x19, 0xa3, 0x98, 0x9d, 0x77, 0x92, 0x18, 0xba, 0x9c, 0x00, 0xda, 0x69, 0xee, 0x84, 0xf9, 0x10, 0xe5, 0xda, 0xf0, 0x7d, 0x78, 0x6c, 0x92, 0xd8, 0xc7, 0x45}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x03, 0x32, 0x71, 0x69, 0x3c, 0x85, 0xca, 0x20, 0xca, 0x0b, 0x22, 0xb2, 0xc2, 0x03, 0x00, 0xce, 0x20, 0x3c, 0xf4, 0xa5, 0x93, 0x4f, 0xe2, 0x1f, 0xf7, 0x07, 0x5c, 0x64, 0xc8, 0x24, 0x21}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf1, 0xde, 0x01, 0x07, 0xe9, 0x1b, 0xfa, 0x7e, 0x51, 0x6b, 0x62, 0xb2, 0x29, 0x6b, 0xb6, 0x0f, 0xeb, 0xd5, 0xf8, 0x08, 0xc1, 0x7c, 0x90, 0xd6, 0x3f, 0xa0, 0xa4, 0x2e, 0x30, 0xef, 0xb5}}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x60, 0x46, 0x90, 0x85, 0xaf, 0x6f, 0xa2, 0x8d, 0x6a, 0x1d, 0x3e, 0xfd, 0x56, 0xd7, 0x57, 0x5e, 0x00, 0x30, 0x5b, 0x49, 0x6c, 0xc4, 0x85, 0xf5, 0x1c, 0x39, 0xef, 0x0b, 0x4b, 0x28} }; R_RSA_PUBLIC_KEY PUBLIC_KEY3; R_RSA_PRIVATE_KEY PRIVATE_KEY3; int KEYPAIR3_READY = 0; int main (argc, argv) int argc; char *argv[]; { R_RANDOM_STRUCT randomStruct; char command[80]; int done = 0; if (SetOptions (argc, argv)) return (0); InitRandomStruct (&randomStruct); PrintMessage ("NOTE: When saving to a file, a filename of \"-\" will output to the screen."); while (!done) { PrintMessage (""); PrintMessage ("S - Sign a file"); PrintMessage ("E - sEal a file"); PrintMessage ("V - Verify a signed file"); PrintMessage ("O - Open a sealed file"); PrintMessage ("G - Generate a keypair (at least 2 minutes)"); PrintMessage ("Q - Quit"); GetCommand (command, sizeof (command), " Enter choice: "); switch (*command) { case '\0': case '#': /* entered a blank line or a comment */ break; case 's': case 'S': DoSignFile (); break; case 'e': case 'E': DoSealFile (&randomStruct); break; case 'v': case 'V': DoVerifyFile (); break; case 'o': case 'O': DoOpenFile (); break; case 'g': case 'G': DoGenerateKeys (&randomStruct); break; case 'Q': case 'q': done = 1; break; default: PrintError ("ERROR: Unrecognized command. Try again.", 0); break; } } R_RandomFinal (&randomStruct); memset ((POINTER)&PRIVATE_KEY3, 0, sizeof (PRIVATE_KEY3)); return (0); } /* Set options from command line and return 0 for success, 1 for bad format. */ static int SetOptions (argc, argv) int argc; char *argv[]; { int i, status = 0; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { status = 1; break; } if (argv[i][1] == 's') SILENT_PROMPT = 1; else if (argv[i][1] == '2') DIGEST_ALGORITHM = DA_MD2; else { status = 1; break; } } if (status) puts ("Usage: rdemo [-s] [-2]\n\ -s silent prompts\n\ -2 use MD2 (not MD5)"); return (status); } /* Initialize the random structure with all zero seed bytes for test purposes. NOTE that this will cause the output of the "random" process to be the same every time. To produce random bytes, the random struct needs random seeds! */ static void InitRandomStruct (randomStruct) R_RANDOM_STRUCT *randomStruct; { static unsigned char seedByte = 0; unsigned int bytesNeeded; R_RandomInit (randomStruct); /* Initialize with all zero seed bytes, which will not yield an actual random number output. */ while (1) { R_GetRandomBytesNeeded (&bytesNeeded, randomStruct); if (bytesNeeded == 0) break; R_RandomUpdate (randomStruct, &seedByte, 1); } } static void DoSignFile () { R_RSA_PRIVATE_KEY *privateKey; char command[80]; int status, recodeFlag; unsigned char content[1000], encodedContent[1000], encodedSignature[MAX_PEM_SIGNATURE_LEN]; unsigned int contentLen, encodedContentLen, encodedSignatureLen; if (ReadText (content, &contentLen, sizeof (content), " Enter filename of content to sign (blank to cancel): ")) return; GetCommand (command, sizeof (command), " ASCII recode the content [y/n] ? (blank to cancel): "); if (! *command) return; else if (*command == 'y' || *command == 'Y') { if (ENCODED_CONTENT_LEN (contentLen) > sizeof (encodedContent)) { PrintError ("ERROR: Not enough room to recode the content", 0); return; } else recodeFlag = 1; } else recodeFlag = 0; if (GetPrivateKey (&privateKey, " Sign as user with private key 1, 2, or 3? (blank to cancel): ")) return; if (status = R_SignPEMBlock (encodedContent, &encodedContentLen, encodedSignature, &encodedSignatureLen, content, contentLen, recodeFlag, DIGEST_ALGORITHM, privateKey)) { PrintError ("signing file", status); return; } if (WriteBlock (encodedSignature, encodedSignatureLen, " Enter filename to save the signature (blank to cancel): ")) return; if (recodeFlag) { if (WriteBlock (encodedContent, encodedContentLen, " Enter filename to save the encoded content (blank to cancel): ")) return; } } static void DoSealFile (randomStruct) R_RANDOM_STRUCT *randomStruct; { R_RSA_PRIVATE_KEY *privateKey; R_RSA_PUBLIC_KEY *publicKey; int status; unsigned char content[1000], encryptedContent[1000], encryptedSignature[MAX_PEM_ENCRYPTED_SIGNATURE_LEN], encryptedKey[MAX_PEM_ENCRYPTED_KEY_LEN], iv[8]; unsigned int contentLen, encryptedContentLen, encryptedSignatureLen, encryptedKeyLen; /* Set up a break point with a do {} while (0) so that we can zeroize the sensitive buffers before exiting. */ do { if (ReadText (content, &contentLen, sizeof (content), " Enter filename of content to seal (blank to cancel): ")) break; if (ENCRYPTED_CONTENT_LEN (contentLen) > sizeof (encryptedContent)) { PrintError ("ERROR: Not enough room to encrypt the content.", 0); break; } if (GetPrivateKey (&privateKey, " Sign as user with private key 1, 2, or 3? (blank to cancel): ")) break; if (GetPublicKey (&publicKey, " Seal for user with public key 1, 2, or 3? (blank to cancel): ")) break; if (status = R_SealPEMBlock (encryptedContent, &encryptedContentLen, encryptedKey, &encryptedKeyLen, encryptedSignature, &encryptedSignatureLen, iv, content, contentLen, DIGEST_ALGORITHM, publicKey, privateKey, randomStruct)) { PrintError ("sealing file", status); break; } if (WriteBlock (encryptedSignature, encryptedSignatureLen, " Enter filename to save the signature (blank to cancel): ")) break; if (WriteBlock (encryptedKey, encryptedKeyLen, " Enter filename to save the encrypted key (blank to cancel): ")) break; if (WriteBlock (iv, 8, " Enter filename to save the key's IV (blank to cancel): ")) break; if (WriteBlock (encryptedContent, encryptedContentLen, " Enter filename to save the encrypted content (blank to cancel): ")) break; } while (0); memset ((POINTER)content, 0, sizeof (content)); } static void DoVerifyFile () { R_RSA_PUBLIC_KEY *publicKey; char command[80]; int status, recodeFlag; unsigned char content[1000], encodedContent[1000], encodedSignature[MAX_PEM_SIGNATURE_LEN]; unsigned int contentLen, encodedContentLen, encodedSignatureLen; GetCommand (command, sizeof (command), " Is the file to verify ASCII recoded [y/n] ? (blank to cancel): "); if (! *command) return; if (*command == 'y' || *command == 'Y') { recodeFlag = 1; if (ReadBlock (encodedContent, &encodedContentLen, sizeof (encodedContent), " Enter name of file to decode and verify (blank to cancel): ")) return; if (DECODED_CONTENT_LEN (encodedContentLen) > sizeof (content)) { PrintError ("ERROR: Not enough room to recode the content", 0); return; } } else { recodeFlag = 0; if (ReadText (encodedContent, &encodedContentLen, sizeof (encodedContent), " Enter name of file to verify (blank to cancel): ")) return; } if (ReadBlock (encodedSignature, &encodedSignatureLen, sizeof (encodedSignature), " Enter filename of signature (blank to cancel): ")) return; if (GetPublicKey (&publicKey, " Verify signature from user with public key 1, 2, or 3? (blank to cancel): ")) return; if (status = R_VerifyPEMSignature (content, &contentLen, encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, recodeFlag, DIGEST_ALGORITHM, publicKey)) { PrintError ("verifying file", status); return; } else PrintMessage ("Signature verified."); if (recodeFlag) { if (WriteBlock (content, contentLen, " Enter filename to save the content (blank to cancel): ")) return; } } static void DoOpenFile () { R_RSA_PRIVATE_KEY *privateKey; R_RSA_PUBLIC_KEY *publicKey; int status; unsigned char content[1000], encryptedContent[1000], encryptedSignature[MAX_PEM_ENCRYPTED_SIGNATURE_LEN], encryptedKey[MAX_PEM_ENCRYPTED_KEY_LEN], iv[8]; unsigned int contentLen, encryptedContentLen, encryptedSignatureLen, encryptedKeyLen, ivLen; /* Set up a break point with a do {} while (0) so that we can zeroize the sensitive buffers before exiting. */ do { if (ReadBlock (encryptedContent, &encryptedContentLen, sizeof (encryptedContent), " Enter filename of content to open (blank to cancel): ")) break; if (DECRYPTED_CONTENT_LEN (encryptedContentLen) > sizeof (content)) { PrintError ("ERROR: Not enough room to decrypt the content.", 0); break; } if (ReadBlock (encryptedSignature, &encryptedSignatureLen, sizeof (encryptedSignature), " Enter filename the signature (blank to cancel): ")) break; if (ReadBlock (encryptedKey, &encryptedKeyLen, sizeof (encryptedKey), " Enter filename of the encrypted key (blank to cancel): ")) break; if (ReadBlock (iv, &ivLen, 8, " Enter filename of the key's IV (blank to cancel): ")) break; if (GetPublicKey (&publicKey, " Verify signature from user with public key 1, 2, or 3? (blank to cancel): ")) break; if (GetPrivateKey (&privateKey, " Open for user with private key 1, 2, or 3? (blank to cancel): ")) break; if (status = R_OpenPEMBlock (content, &contentLen, encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, encryptedSignature, encryptedSignatureLen, iv, DIGEST_ALGORITHM, privateKey, publicKey)) { PrintError ("opening enveloped file", status); break; } else PrintMessage ("Signature verified."); if (WriteBlock (content, contentLen, " Enter filename to save the decrypted content (blank to cancel): ")) break; } while (0); memset ((POINTER)content, 0, sizeof (content)); } static void DoGenerateKeys (randomStruct) R_RANDOM_STRUCT *randomStruct; { R_RSA_PROTO_KEY protoKey; char command[80]; int status, keySize; GetCommand (command, sizeof (command), " Enter key size in bits, (508 to 1024) (blank to cancel): "); if (! *command) return; sscanf (command, "%d", &keySize); protoKey.bits = (unsigned int)keySize; protoKey.useFermat4 = 1; if (status = R_GeneratePEMKeys (&PUBLIC_KEY3, &PRIVATE_KEY3, &protoKey, randomStruct)) { PrintError ("generating keys", status); return; } PrintMessage ("Public key 3 and private key 3 are now ready to use."); KEYPAIR3_READY = 1; WriteKeypair3 (); } static void WriteKeypair3 () { FILE *file; char filename[256]; while (1) { GetCommand (filename, sizeof (filename), "Enter filename to save the keypair (blank to not save): "); if (! *filename) return; if (filename[0] == '-' && filename[1] == '\0') { /* use stdout */ file = stdout; break; } if ((file = fopen (filename, "w")) != NULL) /* successfully opened */ break; PrintError ("ERROR: Cannot open a file with that name. Try again.", 0); } fprintf (file, "Public Key, %u bits:\n", PUBLIC_KEY3.bits); fprintf (file, " modulus: "); WriteBigInteger (file, PUBLIC_KEY3.modulus, sizeof (PUBLIC_KEY3.modulus)); fprintf (file, " exponent: "); WriteBigInteger (file, PUBLIC_KEY3.exponent, sizeof (PUBLIC_KEY3.exponent)); fprintf (file, "\nPrivate Key, %u bits:\n", PRIVATE_KEY3.bits); fprintf (file, " modulus: "); WriteBigInteger (file, PRIVATE_KEY3.modulus, sizeof (PRIVATE_KEY3.modulus)); fprintf (file, " public exponent: "); WriteBigInteger (file, PRIVATE_KEY3.publicExponent, sizeof (PRIVATE_KEY3.publicExponent)); fprintf (file, " exponent: "); WriteBigInteger (file, PRIVATE_KEY3.exponent, sizeof (PRIVATE_KEY3.exponent)); fprintf (file, " prime 1: "); WriteBigInteger (file, PRIVATE_KEY3.prime[0], sizeof (PRIVATE_KEY3.prime[0])); fprintf (file, " prime 2: "); WriteBigInteger (file, PRIVATE_KEY3.prime[1], sizeof (PRIVATE_KEY3.prime[1])); fprintf (file, " prime exponent 1: "); WriteBigInteger (file, PRIVATE_KEY3.primeExponent[0], sizeof (PRIVATE_KEY3.primeExponent[0])); fprintf (file, " prime exponent 2: "); WriteBigInteger (file, PRIVATE_KEY3.primeExponent[1], sizeof (PRIVATE_KEY3.primeExponent[1])); fprintf (file, " coefficient: "); WriteBigInteger (file, PRIVATE_KEY3.coefficient, sizeof (PRIVATE_KEY3.coefficient)); if (file != stdout) fclose (file); } /* Write the byte string 'integer' to 'file', skipping over leading zeros. */ static void WriteBigInteger (file, integer, integerLen) FILE *file; unsigned char *integer; unsigned int integerLen; { while (*integer == 0 && integerLen > 0) { integer++; integerLen--; } if (integerLen == 0) { /* Special case, just print a zero. */ fprintf (file, "00\n"); return; } for (; integerLen > 0; integerLen--) fprintf (file, "%02x ", (unsigned int)(*integer++)); fprintf (file, "\n"); } /* Use the prompt to ask the user to use public key 1, 2 or 3 and point publicKey to the answer. Return 0 on success or 1 if user cancels by entering a blank. */ static int GetPublicKey (publicKey, prompt) R_RSA_PUBLIC_KEY **publicKey; char *prompt; { char command[80]; while (1) { GetCommand (command, sizeof (command), prompt); switch (*command) { case '\0': return (1); case '1': *publicKey = &PUBLIC_KEY1; return (0); case '2': *publicKey = &PUBLIC_KEY2; return (0); case '3': if (!KEYPAIR3_READY) { PrintError ("ERROR: Public key 3 has not been generated yet. Try Again.", 0); break; } else { *publicKey = &PUBLIC_KEY3; return (0); } default: if (KEYPAIR3_READY) PrintError ("ERROR: Please enter 1, 2 or 3. Try again.", 0); else PrintError ("ERROR: Please enter 1 or 2. Try again.", 0); break; } } } /* Use the prompt to ask the user to use private key 1, 2 or 3 and point privateKey to the answer. Return 0 on success or 1 if user cancels by entering a blank. */ static int GetPrivateKey (privateKey, prompt) R_RSA_PRIVATE_KEY **privateKey; char *prompt; { char command[80]; while (1) { GetCommand (command, sizeof (command), prompt); switch (*command) { case '\0': return (1); case '1': *privateKey = &PRIVATE_KEY1; return (0); case '2': *privateKey = &PRIVATE_KEY2; return (0); case '3': if (!KEYPAIR3_READY) { PrintError ("ERROR: Private key 3 has not been generated yet. Try Again.", 0); break; } else { *privateKey = &PRIVATE_KEY3; return (0); } default: if (KEYPAIR3_READY) PrintError ("ERROR: Please enter 1, 2 or 3. Try again.", 0); else PrintError ("ERROR: Please enter 1 or 2. Try again.", 0); break; } } } /* Read a file of up to length maxBlockLen bytes, storing it in block and returning its length in blockLen. Ask for the filename using the given prompt string. Return 0 on success or 1 if error or if user cancels by entering a blank. */ static int ReadBlock (block, blockLen, maxBlockLen, prompt) unsigned char *block; unsigned int *blockLen; unsigned int maxBlockLen; char *prompt; { FILE *file; int status; char filename[256]; unsigned char dummy; while (1) { GetCommand (filename, sizeof (filename), prompt); if (! *filename) return (1); if ((file = fopen (filename, "rb")) != NULL) /* successfully opened */ break; PrintError ("ERROR: Cannot open a file with that name. Try again.", 0); } /* fread () returns the number of items read in. Expect an end of file after the read. */ *blockLen = fread (block, 1, maxBlockLen, file); if (*blockLen == maxBlockLen) /* Read exactly maxBlockLen bytes, so reading one more will set end of file if there were exactly maxBlockLen bytes in the file. */ fread (&dummy, 1, 1, file); if (!feof (file)) { PrintError ("ERROR: Cannot read file or file is too large.", 0); status = 1; } else status = 0; fclose (file); return (status); } /* Read a file of up to length maxBlockLen bytes, storing it in block and returning its length in blockLen. Ask for the filename using the given prompt string. Read the file using fgets and convert all end of line characters to the canonical CR/LF. Return 0 on success or 1 if error or if user cancels by entering a blank. */ static int ReadText (block, blockLen, maxBlockLen, prompt) unsigned char *block; unsigned int *blockLen; unsigned int maxBlockLen; char *prompt; { FILE *file; int status; char filename[256]; unsigned int lineLen; while (1) { GetCommand (filename, sizeof (filename), prompt); if (! *filename) return (1); if ((file = fopen (filename, "rb")) != NULL) /* successfully opened */ break; PrintError ("ERROR: Cannot open a file with that name. Try again.", 0); } status = 0; *blockLen = 0; while (1) { /* fgets returns a null-terminated string which includes the end of line characters. */ if (fgets ((char *)(block + *blockLen), maxBlockLen - *blockLen, file) == NULL) { if (!feof (file)) status = 1; break; } /* Strip of end of line characters. */ lineLen = strlen ((char *)(block + *blockLen)); while (lineLen > 0 && block[*blockLen + lineLen - 1] == 10 || block[*blockLen + lineLen - 1] == 13) lineLen --; /* Now try to add CR/LF. */ (*blockLen) += lineLen; if (*blockLen + 2 > maxBlockLen) { /* Not enough room for CR/LF. */ status = 1; break; } block[(*blockLen)++] = 13; block[(*blockLen)++] = 10; } if (status) PrintError ("ERROR: Cannot read file or file is too large.", 0); fclose (file); return (status); } /* Write block oflength blockLen to a file. Ask for the filename using the given prompt string. Return 0 on success or 1 if error or if user cancels by entering a blank. */ static int WriteBlock (block, blockLen, prompt) unsigned char *block; unsigned int blockLen; char *prompt; { FILE *file; int status; char filename[256]; while (1) { GetCommand (filename, sizeof (filename), prompt); if (! *filename) return (1); if (filename[0] == '-' && filename[1] == '\0') { /* use stdout */ file = stdout; break; } if ((file = fopen (filename, "wb")) != NULL) /* successfully opened */ break; PrintError ("ERROR: Cannot open a file with that name. Try again.", 0); } status = 0; if (fwrite (block, 1, blockLen, file) < blockLen) { PrintError ("ERROR: Cannot write file.", 0); status = 1; } else { if (file == stdout) /* Printing to screen, so print a new line. */ printf ("\n"); } if (file != stdout) fclose (file); return (status); } static void PrintMessage (message) char *message; { if (!SILENT_PROMPT) { puts (message); fflush (stdout); } } /* If type is zero, simply print the task string, otherwise convert the type to a string and print task and type. */ static void PrintError (task, type) char *task; int type; { char *typeString, buf[80]; if (type == 0) { puts (task); return; } /* Convert the type to a string if it is recognized. */ switch (type) { case RE_CONTENT_ENCODING: typeString = "(Encrypted) content has RFC 1113 encoding error"; break; case RE_DIGEST_ALGORITHM: typeString = "Message-digest algorithm is invalid"; break; case RE_KEY: typeString = "Recovered DES key cannot decrypt encrypted content or encrypt signature"; break; case RE_KEY_ENCODING: typeString = "Encrypted key has RFC 1113 encoding error"; break; case RE_MODULUS_LEN: typeString = "Modulus length is invalid"; break; case RE_NEED_RANDOM: typeString = "Random structure is not seeded"; break; case RE_PRIVATE_KEY: typeString = "Private key cannot encrypt message digest, or cannot decrypt encrypted key"; break; case RE_PUBLIC_KEY: typeString = "Public key cannot encrypt DES key, or cannot decrypt signature"; break; case RE_SIGNATURE: typeString = "Signature on content or block is incorrect"; break; case RE_SIGNATURE_ENCODING: typeString = "(Encrypted) signature has RFC 1113 encoding error"; break; default: sprintf (buf, "Code 0x%04x", type); typeString = buf; } printf ("ERROR: %s while %s\n", typeString, task); fflush (stdout); } static void GetCommand (command, maxCommandSize, prompt) char *command; unsigned int maxCommandSize; char *prompt; { unsigned int i; if (!SILENT_PROMPT) { printf ("%s\n", prompt); fflush (stdout); } fgets (command, maxCommandSize, stdin); /* Replace the line terminator with a '\0'. */ for (i = 0; command[i] != '\0'; i++) { if (command[i] == '\012' || command[i] == '\015' || i == (maxCommandSize - 1)) { command[i] = '\0'; return; } } } eBigInteger (file, PUBLIC_KEY3.modulus, sizeof (PUBLIC_KEY3.modulus)); fprintf (file, " exponent: "); Wrsaref/source/0407750006630000000000000000005631776052010010 5 0 1 0 rsaref/source/digit.c1004440006630000000000000464605153737450012033 037777703401 1 0 /* DIGIT.C - digit arithmetic routines */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "nn.h" #include "digit.h" /* Computes a = b * c, where b and c are digits. Lengths: a[2]. */ void NN_DigitMult (a, b, c) NN_DIGIT a[2], b, c; { NN_DIGIT t, u; NN_HALF_DIGIT bHigh, bLow, cHigh, cLow; bHigh = HIGH_HALF (b); bLow = LOW_HALF (b); cHigh = HIGH_HALF (c); cLow = LOW_HALF (c); a[0] = (NN_DIGIT)bLow * (NN_DIGIT)cLow; t = (NN_DIGIT)bLow * (NN_DIGIT)cHigh; u = (NN_DIGIT)bHigh * (NN_DIGIT)cLow; a[1] = (NN_DIGIT)bHigh * (NN_DIGIT)cHigh; if ((t += u) < u) a[1] += TO_HIGH_HALF (1); u = TO_HIGH_HALF (t); if ((a[0] += u) < u) a[1]++; a[1] += HIGH_HALF (t); } /* Sets a = b / c, where a and c are digits. Lengths: b[2]. Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be normalized. */ void NN_DigitDiv (a, b, c) NN_DIGIT *a, b[2], c; { NN_DIGIT t[2], u, v; NN_HALF_DIGIT aHigh, aLow, cHigh, cLow; cHigh = HIGH_HALF (c); cLow = LOW_HALF (c); t[0] = b[0]; t[1] = b[1]; /* Underestimate high half of quotient and subtract. */ if (cHigh == MAX_NN_HALF_DIGIT) aHigh = HIGH_HALF (t[1]); else aHigh = (NN_HALF_DIGIT)(t[1] / (cHigh + 1)); u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow; v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh; if ((t[0] -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u))) t[1]--; t[1] -= HIGH_HALF (u); t[1] -= v; /* Correct estimate. */ while ((t[1] > cHigh) || ((t[1] == cHigh) && (t[0] >= TO_HIGH_HALF (cLow)))) { if ((t[0] -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow)) t[1]--; t[1] -= cHigh; aHigh++; } /* Underestimate low half of quotient and subtract. */ if (cHigh == MAX_NN_HALF_DIGIT) aLow = LOW_HALF (t[1]); else aLow = (NN_HALF_DIGIT) ((NN_DIGIT)(TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) / (cHigh + 1)); u = (NN_DIGIT)aLow * (NN_DIGIT)cLow; v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh; if ((t[0] -= u) > (MAX_NN_DIGIT - u)) t[1]--; if ((t[0] -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v))) t[1]--; t[1] -= HIGH_HALF (v); /* Correct estimate. */ while ((t[1] > 0) || ((t[1] == 0) && t[0] >= c)) { if ((t[0] -= c) > (MAX_NN_DIGIT - c)) t[1]--; aLow++; } *a = TO_HIGH_HALF (aHigh) + aLow; } else { *privateKey = &PRIVATE_KEY3; return (0); } defaulrsaref/source/nn.h1004440006630000000000001006505153737445011347 037777703401 1 0 /* NN.H - header file for NN.C */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ /* Type definitions. */ typedef UINT4 NN_DIGIT; typedef UINT2 NN_HALF_DIGIT; /* Constants. Note: MAX_NN_DIGITS is long enough to hold any RSA modulus, plus one more digit as required by R_GeneratePEMKeys (for n and phiN, whose lengths must be even). All natural numbers have at most MAX_NN_DIGITS digits, except for double-length intermediate values in NN_Mult (t), NN_ModMult (t), NN_ModInv (w), and NN_Div (c). */ /* Length of digit in bits */ #define NN_DIGIT_BITS 32 #define NN_HALF_DIGIT_BITS 16 /* Length of digit in bytes */ #define NN_DIGIT_LEN (NN_DIGIT_BITS / 8) /* Maximum length in digits */ #define MAX_NN_DIGITS \ ((MAX_RSA_MODULUS_LEN + NN_DIGIT_LEN - 1) / NN_DIGIT_LEN + 1) /* Maximum digits */ #define MAX_NN_DIGIT 0xffffffff #define MAX_NN_HALF_DIGIT 0xffff /* Macros. */ #define LOW_HALF(x) (NN_HALF_DIGIT)((x) & MAX_NN_HALF_DIGIT) #define HIGH_HALF(x) \ (NN_HALF_DIGIT)(((x) >> NN_HALF_DIGIT_BITS) & MAX_NN_HALF_DIGIT) #define TO_HIGH_HALF(x) (((NN_DIGIT)(x)) << NN_HALF_DIGIT_BITS) #define DIGIT_MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 1)) & 1) #define DIGIT_2MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 2)) & 3) /* CONVERSIONS NN_Decode (a, digits, b, len) Decodes character string b into a. NN_Encode (a, len, b, digits) Encodes a into character string b. ASSIGNMENTS NN_Assign (a, b, digits) Assigns a = b. NN_ASSIGN_DIGIT (a, b, digits) Assigns a = b, where b is a digit. NN_AssignZero (a, b, digits) Assigns a = 0. NN_Assign2Exp (a, b, digits) Assigns a = 2^b. ARITHMETIC OPERATIONS NN_Add (a, b, c, digits) Computes a = b + c. NN_Sub (a, b, c, digits) Computes a = b - c. NN_Mult (a, b, c, digits) Computes a = b * c. NN_Mod (a, b, bDigits, c, cDigits) Computes a = b mod c. NN_ModMult (a, b, c, d, digits) Computes a = b * c mod d. NN_ModExp (a, b, c, cDigits, d, dDigits) Computes a = b^c mod . NN_ModInv (a, b, c, digits) Computes a = 1/b mod c. NN_Gcd (a, b, c, digits) Computes a = gcd (b, c). OTHER OPERATIONS NN_EVEN (a, digits) Returns 1 iff a is even. NN_Cmp (a, b, digits) Returns sign of a - b. NN_EQUAL (a, digits) Returns 1 iff a = b. NN_Zero (a, digits) Returns 1 iff a = 0. NN_Digits (a, digits) Returns significant length of a in digits. NN_Bits (a, digits) Returns significant length of a in bits. */ void NN_Decode PROTO_LIST ((NN_DIGIT *, unsigned int, unsigned char *, unsigned int)); void NN_Encode PROTO_LIST ((unsigned char *, unsigned int, NN_DIGIT *, unsigned int)); void NN_Assign PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, unsigned int)); void NN_AssignZero PROTO_LIST ((NN_DIGIT *, unsigned int)); void NN_Assign2Exp PROTO_LIST ((NN_DIGIT *, unsigned int, unsigned int)); NN_DIGIT NN_Add PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int)); NN_DIGIT NN_Sub PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int)); void NN_Mult PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int)); void NN_Mod PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); void NN_ModMult PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int)); void NN_ModExp PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); void NN_ModInv PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int)); void NN_Gcd PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int)); int NN_Cmp PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, unsigned int)); int NN_Zero PROTO_LIST ((NN_DIGIT *, unsigned int)); unsigned int NN_Bits PROTO_LIST ((NN_DIGIT *, unsigned int)); unsigned int NN_Digits PROTO_LIST ((NN_DIGIT *, unsigned int)); #define NN_ASSIGN_DIGIT(a, b, digits) {NN_AssignZero (a, digits); a[0] = b;} #define NN_EQUAL(a, b, digits) (! NN_Cmp (a, b, digits)) #define NN_EVEN(a, digits) (((digits) == 0) || ! (a[0] & 1)) pe) char *task; int type; { char *typeString, buf[80]; if (type == 0) { puts (task); return; } /* Convert the type to a string if it is recognized. */ switch (type) { case RE_CONTENT_ENCODING: typeString = "(Encrypted) content has RFC 1113 encoding error"; break; case RE_DIGEST_ALGORITHM: typeString = "Message-digest algorithm is invalid"; break; case RE_KEY: typeString = "Recovered DES key cannot decryptrsaref/source/md5c.c1004440006630000000000002511705153737444011562 037777703401 1 0 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ /* Copyright (C) 1991, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include "global.h" #include "md5.h" /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int)); static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init (context) MD5_CTX *context; /* context */ { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ void MD5Update (context, input, inputLen) MD5_CTX *context; /* context */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) context->count[1]++; context->count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform (context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context->state, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); } /* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */ void MD5Final (digest, context) unsigned char digest[16]; /* message digest */ MD5_CTX *context; /* context */ { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode (bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Update (context, PADDING, padLen); /* Append length (before padding) */ MD5Update (context, bits, 8); /* Store state in digest */ Encode (digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset ((POINTER)context, 0, sizeof (*context)); } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform (state, block) UINT4 state[4]; unsigned char block[64]; { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF ( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF ( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF ( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF ( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF ( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF ( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF ( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF ( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF ( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF ( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF ( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF ( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF ( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF ( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF ( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF ( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG ( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG ( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG ( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG ( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG ( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG ( d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG ( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG ( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG ( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG ( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG ( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG ( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG ( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG ( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG ( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG ( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH ( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH ( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH ( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH ( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH ( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH ( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH ( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH ( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH ( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH ( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH ( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH ( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH ( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH ( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH ( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH ( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II ( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II ( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II ( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II ( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II ( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II ( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II ( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II ( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II ( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II ( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II ( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II ( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II ( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II ( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II ( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II ( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ MD5_memset ((POINTER)x, 0, sizeof (x)); } /* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */ static void Encode (output, input, len) unsigned char *output; UINT4 *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */ static void Decode (output, input, len) UINT4 *output; unsigned char *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } /* Note: Replace "for loop" with standard memcpy if possible. */ static void MD5_memcpy (output, input, len) POINTER output; POINTER input; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. */ static void MD5_memset (output, value, len) POINTER output; int value; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) ((char *)output)[i] = (char)value; } ing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices rsaref/source/md5.h1004440006630000000000000300405153737446011415 037777703401 1 0 /* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ /* MD5 context. */ 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; void MD5Init PROTO_LIST ((MD5_CTX *)); void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init (context) MD5_CTX *context; /* context */ { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing anothersaref/source/md2c.c1004440006630000000000001554605153737426011564 037777703401 1 0 /* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm */ /* Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted for non-commercial Internet Privacy-Enhanced Mail provided that it is identified as the "RSA Data Security, Inc. MD2 Message Digest Algorithm" in all material mentioning or referencing this software or this function. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include "global.h" #include "md2.h" static void MD2Transform PROTO_LIST ((unsigned char [16], unsigned char [16], unsigned char [16])); static void MD2_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD2_memset PROTO_LIST ((POINTER, int, unsigned int)); /* Permutation of 0..255 constructed from the digits of pi. It gives a "random" nonlinear byte substitution operation. */ static unsigned char PI_SUBST[256] = { 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 }; static unsigned char *PADDING[] = { (unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002", (unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004", (unsigned char *)"\005\005\005\005\005", (unsigned char *)"\006\006\006\006\006\006", (unsigned char *)"\007\007\007\007\007\007\007", (unsigned char *)"\010\010\010\010\010\010\010\010", (unsigned char *)"\011\011\011\011\011\011\011\011\011", (unsigned char *)"\012\012\012\012\012\012\012\012\012\012", (unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013", (unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014", (unsigned char *)"\015\015\015\015\015\015\015\015\015\015\015\015\015", (unsigned char *)"\016\016\016\016\016\016\016\016\016\016\016\016\016\016", (unsigned char *) "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017", (unsigned char *) "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020" }; /* MD2 initialization. Begins an MD2 operation, writing a new context. */ void MD2Init (context) MD2_CTX *context; /* context */ { context->count = 0; MD2_memset ((POINTER)context->state, 0, sizeof (context->state)); MD2_memset ((POINTER)context->checksum, 0, sizeof (context->checksum)); } /* MD2 block update operation. Continues an MD2 message-digest operation, processing another message block, and updating the context. */ void MD2Update (context, input, inputLen) MD2_CTX *context; /* context */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ { unsigned int i, index, partLen; /* Update number of bytes mod 16 */ index = context->count; context->count = (index + inputLen) & 0xf; partLen = 16 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { MD2_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD2Transform (context->state, context->checksum, context->buffer); for (i = partLen; i + 15 < inputLen; i += 16) MD2Transform (context->state, context->checksum, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ MD2_memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); } /* MD2 finalization. Ends an MD2 message-digest operation, writing the message digest and zeroizing the context. */ void MD2Final (digest, context) unsigned char digest[16]; /* message digest */ MD2_CTX *context; /* context */ { unsigned int index, padLen; /* Pad out to multiple of 16. */ index = context->count; padLen = 16 - index; MD2Update (context, PADDING[padLen], padLen); /* Extend with checksum */ MD2Update (context, context->checksum, 16); /* Store state in digest */ MD2_memcpy ((POINTER)digest, (POINTER)context->state, 16); /* Zeroize sensitive information. */ MD2_memset ((POINTER)context, 0, sizeof (*context)); } /* MD2 basic transformation. Transforms state and updates checksum based on block. */ static void MD2Transform (state, checksum, block) unsigned char state[16]; unsigned char checksum[16]; unsigned char block[16]; { unsigned int i, j, t; unsigned char x[48]; /* Form encryption block from state, block, state ^ block. */ for (i = 0; i < 16; i++) { x[i] = state[i]; x[i+16] = block[i]; x[i+32] = state[i] ^ block[i]; } /* Encrypt block (18 rounds). */ t = 0; for (i = 0; i < 18; i++) { for (j = 0; j < 48; j++) t = x[j] ^= PI_SUBST[t]; t = (t + i) & 0xff; } /* Save new state */ for (i = 0; i < 16; i++) state[i] = x[i]; /* Update checksum. */ t = checksum[15]; for (i = 0; i < 16; i++) t = checksum[i] ^= PI_SUBST[block[i] ^ t]; /* Zeroize sensitive information. */ MD2_memset ((POINTER)x, 0, sizeof (x)); } /* Note: Replace "for loop" with standard memcpy if possible. */ static void MD2_memcpy (output, input, len) POINTER output; POINTER input; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. */ static void MD2_memset (output, value, len) POINTER output; int value; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) ((char *)output)[i] = (char)value; } vided "as is" without express or implied warranty of any kind. These notices rsaref/source/rsa.h1004440006630000000000000124405153737427011520 037777703401 1 0 /* RSA.H - header file for RSA.C */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ int RSAPublicEncrypt PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *, R_RANDOM_STRUCT *)); int RSAPrivateEncrypt PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); int RSAPublicDecrypt PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *)); int RSAPrivateDecrypt PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); c. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies orsaref/source/targets.mak1004440006630000000000000332005153737430012714 037777703401 1 0 # Dependencies for the TIPEM library # Use a tab before the $(CC) command for portability (UNIX) # Put O=obj or O=o as needed in the makefile # Use $(O) instead of $O for portability (VMS) # Put a space before and after colon ":" for portability (VMS) desc.$(O) : $(SRCDIR)desc.c global.h $(SRCDIR)rsaref.h $(SRCDIR)des.h $(CC) $(CFLAGS) $(SRCDIR)desc.c digit.$(O) : $(SRCDIR)digit.c global.h $(SRCDIR)rsaref.h $(SRCDIR)nn.h\ $(SRCDIR)digit.h $(CC) $(CFLAGS) $(SRCDIR)digit.c md2c.$(O) : $(SRCDIR)md2c.c global.h $(SRCDIR)md2.h $(CC) $(CFLAGS) $(SRCDIR)md2c.c md5c.$(O) : $(SRCDIR)md5c.c global.h $(SRCDIR)md5.h $(CC) $(CFLAGS) $(SRCDIR)md5c.c nn.$(O) : $(SRCDIR)nn.c global.h $(SRCDIR)rsaref.h $(SRCDIR)nn.h\ $(SRCDIR)digit.h $(CC) $(CFLAGS) $(SRCDIR)nn.c prime.$(O) : $(SRCDIR)prime.c global.h $(SRCDIR)rsaref.h $(SRCDIR)nn.h\ $(SRCDIR)prime.h $(CC) $(CFLAGS) $(SRCDIR)prime.c rsa.$(O) : $(SRCDIR)rsa.c global.h $(SRCDIR)rsaref.h $(SRCDIR)r_random.h\ $(SRCDIR)rsa.h $(SRCDIR)nn.h $(CC) $(CFLAGS) $(SRCDIR)rsa.c r_encode.$(O) : $(SRCDIR)r_encode.c global.h $(SRCDIR)rsaref.h\ $(SRCDIR)r_encode.h $(CC) $(CFLAGS) $(SRCDIR)r_encode.c r_enhanc.$(O) : $(SRCDIR)r_enhanc.c global.h $(SRCDIR)rsaref.h\ $(SRCDIR)r_encode.h $(SRCDIR)r_random.h $(SRCDIR)rsa.h $(SRCDIR)md2.h\ $(SRCDIR)md5.h $(SRCDIR)des.h $(CC) $(CFLAGS) $(SRCDIR)r_enhanc.c r_keygen.$(O) : $(SRCDIR)r_keygen.c global.h $(SRCDIR)rsaref.h\ $(SRCDIR)r_random.h $(SRCDIR)nn.h $(CC) $(CFLAGS) $(SRCDIR)r_keygen.c r_random.$(O) : $(SRCDIR)r_random.c global.h $(SRCDIR)rsaref.h\ $(SRCDIR)r_random.h $(SRCDIR)md5.h $(CC) $(CFLAGS) $(SRCDIR)r_random.c r_stdlib.$(O) : $(SRCDIR)r_stdlib.c global.h $(SRCDIR)rsaref.h $(CC) $(CFLAGS) $(SRCDIR)r_stdlib.c es of any part of this documentation and/or software. */ #include "global.h" #include "md2.h" static void MD2Transform PROTO_LIST ((unsigned char [16], unsigned char [16], unsigned char [16])); static void MD2_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD2_memset PROTO_Lrsaref/source/r_random.c1004440006630000000000000570505153737431012530 037777703401 1 0 /* R_RANDOM.C - random objects for RSAREF */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "r_random.h" #include "md5.h" #define RANDOM_BYTES_NEEDED 256 int R_RandomInit (randomStruct) R_RANDOM_STRUCT *randomStruct; /* new random structure */ { randomStruct->bytesNeeded = RANDOM_BYTES_NEEDED; R_memset ((POINTER)randomStruct->state, 0, sizeof (randomStruct->state)); randomStruct->outputAvailable = 0; return (0); } int R_RandomUpdate (randomStruct, block, blockLen) R_RANDOM_STRUCT *randomStruct; /* random structure */ unsigned char *block; /* block of values to mix in */ unsigned int blockLen; /* length of block */ { MD5_CTX context; unsigned char digest[16]; unsigned int i, x; MD5Init (&context); MD5Update (&context, block, blockLen); MD5Final (digest, &context); /* add digest to state */ x = 0; for (i = 0; i < 16; i++) { x += randomStruct->state[15-i] + digest[15-i]; randomStruct->state[15-i] = (unsigned char)x; x >>= 8; } if (randomStruct->bytesNeeded < blockLen) randomStruct->bytesNeeded = 0; else randomStruct->bytesNeeded -= blockLen; /* Zeroize sensitive information. */ R_memset ((POINTER)digest, 0, sizeof (digest)); x = 0; return (0); } int R_GetRandomBytesNeeded (bytesNeeded, randomStruct) unsigned int *bytesNeeded; /* number of mix-in bytes needed */ R_RANDOM_STRUCT *randomStruct; /* random structure */ { *bytesNeeded = randomStruct->bytesNeeded; return (0); } int R_GenerateBytes (block, blockLen, randomStruct) unsigned char *block; /* block */ unsigned int blockLen; /* length of block */ R_RANDOM_STRUCT *randomStruct; /* random structure */ { MD5_CTX context; unsigned int available, i; if (randomStruct->bytesNeeded) return (RE_NEED_RANDOM); available = randomStruct->outputAvailable; while (blockLen > available) { R_memcpy ((POINTER)block, (POINTER)&randomStruct->output[16-available], available); block += available; blockLen -= available; /* generate new output */ MD5Init (&context); MD5Update (&context, randomStruct->state, 16); MD5Final (randomStruct->output, &context); available = 16; /* increment state */ for (i = 0; i < 16; i++) if (randomStruct->state[15-i]++) break; } R_memcpy ((POINTER)block, (POINTER)&randomStruct->output[16-available], blockLen); randomStruct->outputAvailable = available - blockLen; return (0); } void R_RandomFinal (randomStruct) R_RANDOM_STRUCT *randomStruct; /* random structure */ { R_memset ((POINTER)randomStruct, 0, sizeof (*randomStruct)); } text->checksum, context->buffer); for (i = partLen; i rsaref/source/digit.h1004440006630000000000000043605153737432012031 037777703401 1 0 /* DIGIT.H - header file for DIGIT.C */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ void NN_DigitMult PROTO_LIST ((NN_DIGIT [2], NN_DIGIT, NN_DIGIT)); void NN_DigitDiv PROTO_LIST ((NN_DIGIT *, NN_DIGIT [2], NN_DIGIT)); checksum, 16); /* Store state in digest */ MD2_memcpy ((POINTER)digest, (POINTER)context->state, 16); /* Zeroize sensitive information. */ MD2_memset ((POINTER)context, 0, sizeof (*context)); } /* MD2 basic trsaref/source/r_enhanc.c1004440006630000000000004314705153737433012510 037777703401 1 0 /* R_ENHANC.C - cryptographic enhancements for RSAREF */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "r_encode.h" #include "r_random.h" #include "rsa.h" #include "md2.h" #include "md5.h" #include "des.h" /* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5), then DIGEST_INFO_B, then 16-byte message digest. */ static char DIGEST_INFO_A[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02 }; #define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A) static char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 }; #define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B) #define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16) static unsigned char *PADDING[] = { (unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002", (unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004", (unsigned char *)"\005\005\005\005\005", (unsigned char *)"\006\006\006\006\006\006", (unsigned char *)"\007\007\007\007\007\007\007", (unsigned char *)"\010\010\010\010\010\010\010\010" }; #define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN static int R_SignBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int, R_RSA_PRIVATE_KEY *)); static void R_EncodeDigestInfo PROTO_LIST ((unsigned char *, int, unsigned char *)); static void R_EncryptPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, unsigned char [8], unsigned char [8])); static int R_DecryptPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, unsigned char [8], unsigned char [8])); int R_SignPEMBlock (encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, content, contentLen, recode, digestAlgorithm, privateKey) unsigned char *encodedContent; /* encoded content */ unsigned int *encodedContentLen; /* length of encoded content */ unsigned char *encodedSignature; /* encoded signature */ unsigned int *encodedSignatureLen; /* length of encoded signature */ unsigned char *content; /* content */ unsigned int contentLen; /* length of content */ int recode; /* recoding flag */ int digestAlgorithm; /* message-digest algorithm */ R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ { int status; unsigned char signature[MAX_SIGNATURE_LEN]; unsigned int signatureLen; if (status = R_SignBlock (signature, &signatureLen, content, contentLen, digestAlgorithm, privateKey)) return (status); R_EncodePEMBlock (encodedSignature, encodedSignatureLen, signature, signatureLen); if (recode) R_EncodePEMBlock (encodedContent, encodedContentLen, content, contentLen); return (0); } int R_VerifyPEMSignature (content, contentLen, encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, recode, digestAlgorithm, publicKey) unsigned char *content; /* content */ unsigned int *contentLen; /* length of content */ unsigned char *encodedContent; /* (possibly) encoded content */ unsigned int encodedContentLen; /* length of encoded content */ unsigned char *encodedSignature; /* encoded signature */ unsigned int encodedSignatureLen; /* length of encoded signature */ int recode; /* recoding flag */ int digestAlgorithm; /* message-digest algorithm */ R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ { int status; unsigned char signature[MAX_SIGNATURE_LEN]; unsigned int signatureLen; if (encodedSignatureLen > MAX_PEM_SIGNATURE_LEN) return (RE_SIGNATURE_ENCODING); if (recode) { if (status = R_DecodePEMBlock (content, contentLen, encodedContent, encodedContentLen)) return (RE_CONTENT_ENCODING); } else { content = encodedContent; *contentLen = encodedContentLen; } if (status = R_DecodePEMBlock (signature, &signatureLen, encodedSignature, encodedSignatureLen)) return (RE_SIGNATURE_ENCODING); return (R_VerifyBlockSignature (content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey)); } int R_VerifyBlockSignature (block, blockLen, signature, signatureLen, digestAlgorithm, publicKey) unsigned char *block; /* block */ unsigned int blockLen; /* length of block */ unsigned char *signature; /* signature */ unsigned int signatureLen; /* length of signature */ int digestAlgorithm; /* message-digest algorithm */ R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ { int status; unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN], originalDigestInfo[MAX_SIGNATURE_LEN]; unsigned int digestLen, originalDigestInfoLen; if (signatureLen > MAX_SIGNATURE_LEN) return (RE_SIGNATURE); do { if (status = R_DigestBlock (digest, &digestLen, block, blockLen, digestAlgorithm)) break; R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest); if (status = RSAPublicDecrypt (originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, publicKey)) { status = RE_PUBLIC_KEY; break; } if ((originalDigestInfoLen != DIGEST_INFO_LEN) || (R_memcmp ((POINTER)originalDigestInfo, (POINTER)digestInfo, DIGEST_INFO_LEN))) { status = RE_SIGNATURE; break; } } while (0); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)digest, 0, sizeof (digest)); R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo)); R_memset ((POINTER)originalDigestInfo, 0, sizeof (originalDigestInfo)); return (status); } int R_SealPEMBlock (encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, encryptedSignature, encryptedSignatureLen, iv, content, contentLen, digestAlgorithm, publicKey, privateKey, randomStruct) unsigned char *encryptedContent; /* encoded, encrypted content */ unsigned int *encryptedContentLen; /* length */ unsigned char *encryptedKey; /* encoded, encrypted key */ unsigned int *encryptedKeyLen; /* length */ unsigned char *encryptedSignature; /* encoded, encrypted signature */ unsigned int *encryptedSignatureLen; /* length */ unsigned char iv[8]; /* DES initializing vector */ unsigned char *content; /* content */ unsigned int contentLen; /* length of content */ int digestAlgorithm; /* message-digest algorithm */ 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 */ { int status; unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], key[8], signature[MAX_SIGNATURE_LEN]; unsigned int encryptedKeyBlockLen, signatureLen; do { if (status = R_SignBlock (signature, &signatureLen, content, contentLen, digestAlgorithm, privateKey)) break; if ((status = R_GenerateBytes (key, 8, randomStruct)) || (status = R_GenerateBytes (iv, 8, randomStruct))) break; R_EncryptPEMBlock (encryptedContent, encryptedContentLen, content, contentLen, key, iv); if (status = RSAPublicEncrypt (encryptedKeyBlock, &encryptedKeyBlockLen, key, 8, publicKey, randomStruct)) { status = RE_PUBLIC_KEY; break; } R_EncodePEMBlock (encryptedKey, encryptedKeyLen, encryptedKeyBlock, encryptedKeyBlockLen); R_EncryptPEMBlock (encryptedSignature, encryptedSignatureLen, signature, signatureLen, key, iv); } while (0); /* Zeroize sensitive information. */ R_memset ((POINTER)key, 0, sizeof (key)); R_memset ((POINTER)signature, 0, sizeof (signature)); return (status); } int R_OpenPEMBlock (content, contentLen, encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, encryptedSignature, encryptedSignatureLen, iv, digestAlgorithm, privateKey, publicKey) unsigned char *content; /* content */ unsigned int *contentLen; /* length of content */ unsigned char *encryptedContent; /* encoded, encrypted content */ unsigned int encryptedContentLen; /* length */ unsigned char *encryptedKey; /* encoded, encrypted key */ unsigned int encryptedKeyLen; /* length */ unsigned char *encryptedSignature; /* encoded, encrypted signature */ unsigned int encryptedSignatureLen; /* length */ unsigned char iv[8]; /* DES initializing vector */ int digestAlgorithm; /* message-digest algorithm */ R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ { int status; unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], key[MAX_ENCRYPTED_KEY_LEN], signature[MAX_SIGNATURE_LEN]; unsigned int encryptedKeyBlockLen, keyLen, signatureLen; if (encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN) return (RE_KEY_ENCODING); if (encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN) return (RE_SIGNATURE_ENCODING); do { if (status = R_DecodePEMBlock (encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey, encryptedKeyLen)) { status = RE_KEY_ENCODING; break; } if (status = RSAPrivateDecrypt (key, &keyLen, encryptedKeyBlock, encryptedKeyBlockLen, privateKey)) { status = RE_PRIVATE_KEY; break; } if (keyLen != 8) { status = RE_PRIVATE_KEY; break; } if (status = R_DecryptPEMBlock (content, contentLen, encryptedContent, encryptedContentLen, key, iv)) { if ((status == RE_LEN || status == RE_ENCODING)) status = RE_CONTENT_ENCODING; else status = RE_KEY; break; } if (status = R_DecryptPEMBlock (signature, &signatureLen, encryptedSignature, encryptedSignatureLen, key, iv)) { if ((status == RE_LEN || status == RE_ENCODING)) status = RE_SIGNATURE_ENCODING; else status = RE_KEY; } if (status = R_VerifyBlockSignature (content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey)) break; } while (0); /* Zeroize sensitive information. */ R_memset ((POINTER)key, 0, sizeof (key)); R_memset ((POINTER)signature, 0, sizeof (signature)); return (status); } static 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 */ { int status; unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN]; unsigned int digestLen; do { if (status = R_DigestBlock (digest, &digestLen, block, blockLen, digestAlgorithm)) break; R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest); if (status = RSAPrivateEncrypt (signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey)) { status = RE_PRIVATE_KEY; break; } } while (0); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)digest, 0, sizeof (digest)); R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo)); return (status); } int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm) unsigned char *digest; /* message digest */ unsigned int *digestLen; /* length of message digest */ unsigned char *block; /* block */ unsigned int blockLen; /* length of block */ int digestAlgorithm; /* message-digest algorithm */ { MD2_CTX md2Context; MD5_CTX md5Context; int status; status = 0; switch (digestAlgorithm) { case DA_MD2: MD2Init (&md2Context); MD2Update (&md2Context, block, blockLen); MD2Final (digest, &md2Context); *digestLen = 16; break; case DA_MD5: MD5Init (&md5Context); MD5Update (&md5Context, block, blockLen); MD5Final (digest, &md5Context); *digestLen = 16; break; default: status = RE_DIGEST_ALGORITHM; } return (status); } /* Assumes digestAlgorithm is DA_MD2 or DA_MD5 and digest length is 16. */ static void R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest) unsigned char *digestInfo; /* DigestInfo encoding */ int digestAlgorithm; /* message-digest algorithm */ unsigned char *digest; /* message digest */ { R_memcpy ((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN); digestInfo[DIGEST_INFO_A_LEN] = (digestAlgorithm == DA_MD2) ? (unsigned char)2 : (unsigned char)5; R_memcpy ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B, DIGEST_INFO_B_LEN); R_memcpy ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN], (POINTER)digest, 16); } static void R_EncryptPEMBlock (encryptedBlock, encryptedBlockLen, block, blockLen, key, iv) unsigned char *encryptedBlock; /* encrypted, encoded block */ unsigned int *encryptedBlockLen; /* length */ unsigned char *block; /* block */ unsigned int blockLen; /* length of block */ unsigned char key[8]; /* DES key */ unsigned char iv[8]; /* DES initialization vector */ { DES_CBC_CTX context; unsigned char encryptedPart[24], lastPart[24]; unsigned int i, lastPartLen, len, padLen; DES_CBCInit (&context, key, iv, 1); for (i = 0; i < blockLen/24; i++) { DES_CBCUpdate (&context, encryptedPart, &block[24*i], 24); /* len is always 32 */ R_EncodePEMBlock (&encryptedBlock[32*i], &len, encryptedPart, 24); } padLen = 8 - (blockLen % 8); lastPartLen = blockLen - 24*i + padLen; R_memcpy ((POINTER)lastPart, (POINTER)&block[24*i], lastPartLen - padLen); R_memcpy ((POINTER)&lastPart[lastPartLen - padLen], PADDING[padLen], padLen); DES_CBCUpdate (&context, encryptedPart, lastPart, lastPartLen); R_EncodePEMBlock (&encryptedBlock[32*i], &len, encryptedPart, lastPartLen); *encryptedBlockLen = 32*i + len; DES_CBCFinal (&context); /* Zeroize sensitive information. */ R_memset ((POINTER)lastPart, 0, sizeof (lastPart)); } static int R_DecryptPEMBlock (block, blockLen, encryptedBlock, encryptedBlockLen, key, iv) unsigned char *block; /* block */ unsigned int *blockLen; /* length of block */ unsigned char *encryptedBlock; /* encrypted, encoded block */ unsigned int encryptedBlockLen; /* length */ unsigned char key[8]; /* DES key */ unsigned char iv[8]; /* DES initialization vector */ { DES_CBC_CTX context; int status; unsigned char encryptedPart[24], lastPart[24]; unsigned int i, lastPartLen, len, padLen; if (encryptedBlockLen < 1) return (RE_LEN); DES_CBCInit (&context, key, iv, 0); status = 0; do { for (i = 0; i < (encryptedBlockLen-1)/32; i++) { /* len is always 24 */ if (status = R_DecodePEMBlock (encryptedPart, &len, &encryptedBlock[32*i], 32)) break; DES_CBCUpdate (&context, &block[24*i], encryptedPart, 24); } if (status) break; len = encryptedBlockLen - 32*i; if (status = R_DecodePEMBlock (encryptedPart, &lastPartLen, &encryptedBlock[32*i], len)) break; if (lastPartLen % 8) { status = RE_DATA; break; } DES_CBCUpdate (&context, lastPart, encryptedPart, lastPartLen); padLen = lastPart[lastPartLen - 1]; if (padLen > 8) { status = RE_DATA; break; } if (R_memcmp ((POINTER)&lastPart[lastPartLen - padLen], PADDING[padLen], padLen)) { status = RE_DATA; break; } R_memcpy ((POINTER)&block[24*i], (POINTER)lastPart, lastPartLen - padLen); *blockLen = 24*i + lastPartLen - padLen; } while (0); DES_CBCFinal (&context); /* Zeroize sensitive information. */ R_memset ((POINTER)lastPart, 0, sizeof (lastPart)); return (status); } SignBlock (signature, &signatureLen, content, contentLen, digestAlgorithm, privateKey)) break; if ((status = R_GenerateBytes (key, 8, randomStruct)) || (status = R_GenerateBytes (iv, 8, randomStruct))) break; R_EncryptPEMBlock (encryptedContent, encryptedContentLen, content, contentLen, key, iv); if (status = RSAPublicEncrypt (encryrsaref/source/r_random.h1004440006630000000000000036405153737433012533 037777703401 1 0 /* R_RANDOM.H - header file for R_RANDOM.C */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ int R_GenerateBytes PROTO_LIST ((unsigned char *, unsigned int, R_RANDOM_STRUCT *)); ed char *content; /* content */ unsigned int *contentLen; /* length of content */ unsigned char *encryptedContent; /* encoded, encrypted content */ unsigned int encryptedContentLen; rsaref/source/desc.c1004440006630000000000002431605153737434011647 037777703401 1 0 /* DESC.C - Data Encryption Standard routines for RSAREF */ #include "global.h" #include "rsaref.h" #include "des.h" /* Initial permutation IP. */ unsigned char IP[64] = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }; /* Final permutation FP = IP^{-1}. */ unsigned char FP[64] = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 }; /* Permuted-choice 1. */ unsigned char PC1[] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 }; /* Left shifts for the key schedule. */ unsigned char LS[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; /* Permuted-choice 2. */ unsigned char PC2[] = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 }; /* Bit-selection table E. */ unsigned char E[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 }; /* Selection functions (S-boxes). [[These are 0-origin indexed.]] */ unsigned char S[8][64] = { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 }; /* Permutation P. */ unsigned char P[32] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 }; static void Unpack PROTO_LIST ((unsigned char *, unsigned char *, unsigned int)); static void Pack PROTO_LIST ((unsigned char *, unsigned char *, unsigned int)); /* DES-CBC initialization. Begins a DES-CBC operation, writing a new context. */ void DES_CBCInit (context, key, iv, encrypt) DES_CBC_CTX *context; /* DES-CBC context */ unsigned char key[8]; /* DES key */ unsigned char iv[8]; /* DES initializing vector */ int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ { unsigned char CD[56], keyBit[64], t; unsigned int i, j; /* Copy encrypt flag to context. */ context->encrypt = encrypt; /* Unpack initializing vector into context. */ Unpack (context->ivBit, iv, 8); /* Unpack key and generate C and D by permuting the key according to PC1. */ Unpack (keyBit, key, 8); for (i = 0; i < 56; i++) CD[i] = keyBit[PC1[i]-1]; /* Generate subkeys Ki by rotating C and D according to schedule and permuting C and D according to PC2. */ for (i = 0; i < 16; i++) { for (j = 0; j < LS[i]; j++) { t = CD[0]; R_memcpy ((POINTER)CD, (POINTER)&CD[1], 27); CD[27] = t; t = CD[28]; R_memcpy ((POINTER)&CD[28], (POINTER)&CD[29], 27); CD[55] = t; } for (j = 0; j < 48; j++) context->subkeyBit[i][j] = CD[PC2[j]-1]; } /* Zeroize sensitive information. */ R_memset ((POINTER)CD, 0, sizeof (CD)); R_memset ((POINTER)keyBit, 0, sizeof (keyBit)); } /* DES-CBC block update operation. Continues a DES-CBC encryption operation, processing eight-byte message blocks, and updating the context. */ int DES_CBCUpdate (context, output, input, len) DES_CBC_CTX *context; /* DES-CBC context */ unsigned char *output; /* output block */ unsigned char *input; /* input block */ unsigned int len; /* length of input and output blocks */ { unsigned char inputBit[64], LR[64], newL[32], outputBit[64], sInput[48], sOutput[32], t; unsigned int i, j, k; if (len % 8) return (RE_LEN); for (i = 0; i < len/8; i++) { /* Unpack input block and set LR = IP(input ^ iv) (encrypt) or LR = IP(input) (decrypt). */ Unpack (inputBit, &input[8*i], 8); if (context->encrypt) for (j = 0; j < 64; j++) LR[j] = inputBit[IP[j]-1] ^ context->ivBit[IP[j]-1]; else for (j = 0; j < 64; j++) LR[j] = inputBit[IP[j]-1]; /* 16 rounds. */ for (j = 0; j < 16; j++) { /* Save R, which will be the new L. */ R_memcpy ((POINTER)newL, &LR[32], 32); /* Compute sInput = E(R) ^ Kj (encrypt) or sInput = E(R) ^ K{15-j} (decrypt). */ if (context->encrypt) for (k = 0; k < 48; k++) sInput[k] = LR[E[k]+31] ^ context->subkeyBit[j][k]; else for (k = 0; k < 48; k++) sInput[k] = LR[E[k]+31] ^ context->subkeyBit[15-j][k]; /* Apply eight S boxes. Index into S box k is formed from these bits of sInput: 6*k 6*k+5 6*k+1 6*k+2 6*k+3 6*k+4 Value of S box k becomes these bits of sOutput: 4*k 4*k+1 4*k+2 4*k+3 */ for (k = 0; k < 8; k++) { t = S[k][(sInput[6*k] << 5) | (sInput[6*k + 5] << 4) | (sInput[6*k + 1] << 3) | (sInput[6*k + 2] << 2) | (sInput[6*k + 3] << 1) | (sInput[6*k + 4] << 0)]; sOutput[4*k] = (unsigned char)((t >> 3) & 1); sOutput[4*k + 1] = (unsigned char)((t >> 2) & 1); sOutput[4*k + 2] = (unsigned char)((t >> 1) & 1); sOutput[4*k + 3] = (unsigned char)(t & 1); } /* Compute new R = L ^ P(sOutput). */ for (k = 0; k < 32; k++) LR[k+32] = LR[k] ^ sOutput[P[k]-1]; /* Restore new L. */ R_memcpy ((POINTER)LR, (POINTER)newL, 32); } /* Exchange L and R. */ R_memcpy ((POINTER)newL, (POINTER)&LR[32], 32); R_memcpy ((POINTER)&LR[32], (POINTER)LR, 32); R_memcpy ((POINTER)LR, (POINTER)newL, 32); /* Set output = FP(LR) (encrypt) or FP(LR) ^ iv (decrypt), and pack output block. */ if (context->encrypt) for (j = 0; j < 64; j++) outputBit[j] = LR[FP[j]-1]; else for (j = 0; j < 64; j++) outputBit[j] = LR[FP[j]-1] ^ context->ivBit[j]; Pack (&output[8*i], outputBit, 8); /* Set iv = output (encrypt) or iv = input (decrypt). */ if (context->encrypt) R_memcpy ((POINTER)context->ivBit, (POINTER)outputBit, 64); else R_memcpy ((POINTER)context->ivBit, (POINTER)inputBit, 64); } /* Zeroize sensitive information. */ R_memset ((POINTER)inputBit, 0, sizeof (inputBit)); R_memset ((POINTER)LR, 0, sizeof (LR)); R_memset ((POINTER)newL, 0, sizeof (newL)); R_memset ((POINTER)outputBit, 0, sizeof (outputBit)); R_memset ((POINTER)sInput, 0, sizeof (sInput)); R_memset ((POINTER)sOutput, 0, sizeof (sOutput)); t = 0; return (0); } /* DES-CBC finalization operation. Ends a DES-CBC encryption operation, zeroizing the context. */ void DES_CBCFinal (context) DES_CBC_CTX *context; { R_memset ((POINTER)context, 0, sizeof (*context)); } static void Unpack (bit, block, blockLen) unsigned char *bit; /* bit array */ unsigned char *block; /* byte array */ unsigned int blockLen; /* length of byte array */ { unsigned int i, j; unsigned char t; for (i = 0; i < blockLen; i++) { t = block[i]; for (j = 0; j < 8; j++) bit[8*i + j] = (unsigned char)((t >> (7-j)) & 1); } } static void Pack (block, bit, blockLen) unsigned char *block; /* byte array */ unsigned char *bit; /* bit array */ unsigned int blockLen; /* length of byte array */ { unsigned int i, j; unsigned char t; for (i = 0; i < blockLen; i++) { t = 0; for (j = 0; j < 8; j++) t |= bit[8*i +j] << (7-j); block[i] = t; } } 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }; /* Final permutation FP = IP^{-1}. */ unsigned char FP[64] = { 40,rsaref/source/des.h1004440006630000000000000124505153737435011506 037777703401 1 0 /* DES.H - header file for DESC.C */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ /* DES-CBC context. */ typedef struct { unsigned char subkeyBit[16][48]; /* subkeys */ unsigned char ivBit[64]; /* initializing vector */ int encrypt; /* encrypt flag */ } DES_CBC_CTX; void DES_CBCInit PROTO_LIST ((DES_CBC_CTX *, unsigned char *, unsigned char *, int)); int DES_CBCUpdate PROTO_LIST ((DES_CBC_CTX *, unsigned char *, unsigned char *, unsigned int)); void DES_CBCFinal PROTO_LIST ((DES_CBC_CTX *)); n functions (S-boxes). [[These are 0-origin indexed.]] */ unsigned char S[8][64] = { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 1rsaref/source/r_stdlib.c1004440006630000000000000234405153737436012532 037777703401 1 0 /* R_STDLIB.C - platform-specific C library routines for RSAREF */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include void R_memset (output, value, len) POINTER output; /* output block */ int value; /* value */ unsigned int len; /* length of block */ { if (len) memset (output, value, len); } void R_memcpy (output, input, len) POINTER output; /* output block */ POINTER input; /* input block */ unsigned int len; /* length of blocks */ { if (len) memcpy (output, input, len); } int R_memcmp (firstBlock, secondBlock, len) POINTER firstBlock; /* first block */ POINTER secondBlock; /* second block */ unsigned int len; /* length of blocks */ { if (len) return (memcmp (firstBlock, secondBlock, len)); else return (0); } 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 }; /* Permutation P. */ unsigned char P[32] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 }; staticrsaref/source/prime.c1004440006630000000000001112605153737437012043 037777703401 1 0 /* PRIME.C - primality-testing routines */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "nn.h" #include "prime.h" static unsigned int SMALL_PRIMES[] = { 3, 5, 7, 11 }; #define SMALL_PRIME_COUNT 4 static int RSAPrime PROTO_LIST ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); static int ProbablePrime PROTO_LIST ((NN_DIGIT *, unsigned int)); static int SmallFactor PROTO_LIST ((NN_DIGIT *, unsigned int)); static int FermatTest PROTO_LIST ((NN_DIGIT *, unsigned int)); static int RelativelyPrime PROTO_LIST ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); /* Find a probable prime a between 3*2^(b-2) and 2^b-1, starting at 3*2^(b-2) + (c mod 2^(b-2)), such that gcd (a-1, d) = 1. Lengths: a[cDigits], c[cDigits], d[dDigits]. Assumes b > 2, b < cDigits * NN_DIGIT_BITS, d is odd, cDigits < MAX_NN_DIGITS, dDigits < MAX_NN_DIGITS, and a probable prime can be found. */ void FindRSAPrime (a, b, c, cDigits, d, dDigits) NN_DIGIT *a, *c, *d; unsigned int b, cDigits, dDigits; { NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS], w[MAX_NN_DIGITS]; /* Compute t = 2^(b-2), u = 3*2^(b-2). */ NN_Assign2Exp (t, b-2, cDigits); NN_Assign2Exp (u, b-1, cDigits); NN_Add (u, u, t, cDigits); /* Compute v = 3*2^(b-2) + (c mod 2^(b-2)); add one if even. */ NN_Mod (v, c, cDigits, t, cDigits); NN_Add (v, v, u, cDigits); if (NN_EVEN (v, cDigits)) { NN_ASSIGN_DIGIT (w, 1, cDigits); NN_Add (v, v, w, cDigits); } /* Compute w = 2, u = 2^b - 2. */ NN_ASSIGN_DIGIT (w, 2, cDigits); NN_Sub (u, u, w, cDigits); NN_Add (u, u, t, cDigits); /* Search to 2^b-1 from starting point, then from 3*2^(b-2)+1. */ while (! RSAPrime (v, cDigits, d, dDigits)) { if (NN_Cmp (v, u, cDigits) > 0) NN_Sub (v, v, t, cDigits); NN_Add (v, v, w, cDigits); } NN_Assign (a, v, cDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)v, 0, sizeof (v)); } /* Returns nonzero iff a is a probable prime and GCD (a-1, b) = 1. Lengths: a[aDigits], b[bDigits]. Assumes aDigits < MAX_NN_DIGITS, bDigits < MAX_NN_DIGITS. */ static int RSAPrime (a, aDigits, b, bDigits) NN_DIGIT *a, *b; unsigned int aDigits, bDigits; { int status; NN_DIGIT aMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; NN_ASSIGN_DIGIT (t, 1, aDigits); NN_Sub (aMinus1, a, t, aDigits); status = ProbablePrime (a, aDigits) && RelativelyPrime (aMinus1, aDigits, b, bDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)aMinus1, 0, sizeof (aMinus1)); return (status); } /* Returns nonzero iff a is a probable prime. Lengths: a[aDigits]. Assumes aDigits < MAX_NN_DIGITS. */ static int ProbablePrime (a, aDigits) NN_DIGIT *a; unsigned int aDigits; { return (! SmallFactor (a, aDigits) && FermatTest (a, aDigits)); } /* Returns nonzero iff a has a prime factor in SMALL_PRIMES. Lengths: a[aDigits]. Assumes aDigits < MAX_NN_DIGITS. */ static int SmallFactor (a, aDigits) NN_DIGIT *a; unsigned int aDigits; { int status; NN_DIGIT t[1]; unsigned int i; status = 0; for (i = 0; i < SMALL_PRIME_COUNT; i++) { NN_ASSIGN_DIGIT (t, SMALL_PRIMES[i], 1); NN_Mod (t, a, aDigits, t, 1); if (NN_Zero (t, 1)) { status = 1; break; } } /* Zeroize sensitive information. */ i = 0; R_memset ((POINTER)t, 0, sizeof (t)); return (status); } /* Returns nonzero iff a passes Fermat's test for witness 2. (All primes pass the test, and nearly all composites fail.) Lengths: a[aDigits]. Assumes aDigits < MAX_NN_DIGITS. */ static int FermatTest (a, aDigits) NN_DIGIT *a; unsigned int aDigits; { int status; NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; NN_ASSIGN_DIGIT (t, 2, aDigits); NN_ModExp (u, t, a, aDigits, a, aDigits); status = NN_EQUAL (t, u, aDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)u, 0, sizeof (u)); return (status); } /* Returns nonzero iff a and b are relatively prime. Lengths: a[aDigits], b[bDigits]. Assumes aDigits >= bDigits, aDigits < MAX_NN_DIGITS. */ static int RelativelyPrime (a, aDigits, b, bDigits) NN_DIGIT *a, *b; unsigned int aDigits, bDigits; { int status; NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; NN_AssignZero (t, aDigits); NN_Assign (t, b, bDigits); NN_Gcd (t, a, t, aDigits); NN_ASSIGN_DIGIT (u, 1, aDigits); status = NN_EQUAL (t, u, aDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)t, 0, sizeof (t)); return (status); } return (0); } /* DES-CBC finalization operation. Ends a DES-CBC encryption operation, zeroizing the context. */ void DES_CBCFinal (context) DES_CBC_CTX *context; { R_memset ((POINTER)context, 0, sizeof (*context)); } static void Unpack (bit, block, blockLen) unsigned char *bit; /* bit array */ unsigned char *block; /* byte array */rsaref/source/r_keygen.c1004440006630000000000001025405326645454012532 037777703401 1 0 /* R_KEYGEN.C - key-pair generation for RSAREF */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "r_random.h" #include "nn.h" #include "prime.h" static int GenerateDigits PROTO_LIST ((NN_DIGIT *, unsigned int, R_RANDOM_STRUCT *)); /* Generates an RSA key pair with a given length and public exponent. */ 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 */ { NN_DIGIT d[MAX_NN_DIGITS], dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], e[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], phiN[MAX_NN_DIGITS], pMinus1[MAX_NN_DIGITS], q[MAX_NN_DIGITS], qInv[MAX_NN_DIGITS], qMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; int status; unsigned int nDigits, pDigits; if ((protoKey->bits < MIN_RSA_MODULUS_BITS) || (protoKey->bits > MAX_RSA_MODULUS_BITS)) return (RE_MODULUS_LEN); nDigits = (protoKey->bits + NN_DIGIT_BITS - 1) / NN_DIGIT_BITS; pDigits = (nDigits + 1) / 2; /* Generate random RSA primes p and q so that product has correct length. */ if ((status = GenerateDigits (p, pDigits, randomStruct)) || (status = GenerateDigits (q, pDigits, randomStruct))) return (status); /* NOTE: for 65537, this assumes NN_DIGIT is at least 17 bits. */ NN_ASSIGN_DIGIT (e, protoKey->useFermat4 ? (NN_DIGIT)65537 : (NN_DIGIT)3, nDigits); FindRSAPrime (p, (protoKey->bits + 1) / 2, p, pDigits, e, 1); FindRSAPrime (q, protoKey->bits / 2, q, pDigits, e, 1); /* Sort so that p > q. (p = q case is extremely unlikely.) */ if (NN_Cmp (p, q, pDigits) < 0) { NN_Assign (t, p, pDigits); NN_Assign (p, q, pDigits); NN_Assign (q, t, pDigits); } /* Compute n = pq, qInv = q^{-1} mod p, d = e^{-1} mod (p-1)(q-1), dP = d mod p-1, dQ = d mod q-1. */ NN_Mult (n, p, q, pDigits); NN_ModInv (qInv, q, p, pDigits); NN_ASSIGN_DIGIT (t, 1, pDigits); NN_Sub (pMinus1, p, t, pDigits); NN_Sub (qMinus1, q, t, pDigits); NN_Mult (phiN, pMinus1, qMinus1, pDigits); NN_ModInv (d, e, phiN, nDigits); NN_Mod (dP, d, nDigits, pMinus1, pDigits); NN_Mod (dQ, d, nDigits, qMinus1, pDigits); publicKey->bits = privateKey->bits = protoKey->bits; NN_Encode (publicKey->modulus, MAX_RSA_MODULUS_LEN, n, nDigits); NN_Encode (publicKey->exponent, MAX_RSA_MODULUS_LEN, e, 1); R_memcpy ((POINTER)privateKey->modulus, (POINTER)publicKey->modulus, MAX_RSA_MODULUS_LEN); R_memcpy ((POINTER)privateKey->publicExponent, (POINTER)publicKey->exponent, MAX_RSA_MODULUS_LEN); NN_Encode (privateKey->exponent, MAX_RSA_MODULUS_LEN, d, nDigits); NN_Encode (privateKey->prime[0], MAX_RSA_PRIME_LEN, p, pDigits); NN_Encode (privateKey->prime[1], MAX_RSA_PRIME_LEN, q, pDigits); NN_Encode (privateKey->primeExponent[0], MAX_RSA_PRIME_LEN, dP, pDigits); NN_Encode (privateKey->primeExponent[1], MAX_RSA_PRIME_LEN, dQ, pDigits); NN_Encode (privateKey->coefficient, MAX_RSA_PRIME_LEN, qInv, pDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)d, 0, sizeof (d)); R_memset ((POINTER)dP, 0, sizeof (dP)); R_memset ((POINTER)dQ, 0, sizeof (dQ)); R_memset ((POINTER)p, 0, sizeof (p)); R_memset ((POINTER)phiN, 0, sizeof (phiN)); R_memset ((POINTER)pMinus1, 0, sizeof (pMinus1)); R_memset ((POINTER)q, 0, sizeof (q)); R_memset ((POINTER)qInv, 0, sizeof (qInv)); R_memset ((POINTER)qMinus1, 0, sizeof (qMinus1)); R_memset ((POINTER)t, 0, sizeof (t)); return (0); } static int GenerateDigits (a, digits, randomStruct) NN_DIGIT *a; R_RANDOM_STRUCT *randomStruct; unsigned int digits; { int status; unsigned char t[MAX_RSA_MODULUS_LEN]; if (status = R_GenerateBytes (t, digits * NN_DIGIT_LEN, randomStruct)) return (status); NN_Decode (a, digits, t, digits * NN_DIGIT_LEN); /* Zeroize sensitive information. */ R_memset ((POINTER)t, 0, sizeof (t)); return (0); } 37777703401 1 0 rsaref/source/prime.h1004440006630000000000000041505153737440012041 037777703401 1 0 /* PRIME.H - header file for PRIME.C */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ void FindRSAPrime PROTO_LIST ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); 2^(b-2)), such that gcd (a-1, d) = 1. Lengths: a[cDigits], c[cDigits], d[dDigits]. Assumes b > 2, b < cDigits * NN_DIGIT_BITS, d is odd, cDigits < MAX_NN_DIGITS, dDigits < MAX_NN_DIGITS, and a probable prime can brsaref/source/rsa.c1004440006630000000000002407205153737441011513 037777703401 1 0 /* RSA.C - RSA routines for RSAREF */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "r_random.h" #include "rsa.h" #include "nn.h" static int RSAPublicBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *)); static int RSAPrivateBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); /* RSA public-key encryption, according to PKCS #1. */ int RSAPublicEncrypt (output, outputLen, input, inputLen, publicKey, randomStruct) unsigned char *output; /* output block */ unsigned int *outputLen; /* length of output block */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ R_RANDOM_STRUCT *randomStruct; /* random structure */ { int status; unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN]; unsigned int i, modulusLen; modulusLen = (publicKey->bits + 7) / 8; if (inputLen + 11 > modulusLen) return (RE_LEN); pkcsBlock[0] = 0; /* block type 2 */ pkcsBlock[1] = 2; for (i = 2; i < modulusLen - inputLen - 1; i++) { /* Find nonzero random byte. */ do { R_GenerateBytes (&byte, 1, randomStruct); } while (byte == 0); pkcsBlock[i] = byte; } /* separator */ pkcsBlock[i++] = 0; R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); status = RSAPublicBlock (output, outputLen, pkcsBlock, modulusLen, publicKey); /* Zeroize sensitive information. */ byte = 0; R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock)); return (status); } /* RSA public-key decryption, according to PKCS #1. */ int RSAPublicDecrypt (output, outputLen, input, inputLen, publicKey) unsigned char *output; /* output block */ unsigned int *outputLen; /* length of output block */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ { int status; unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; unsigned int i, modulusLen, pkcsBlockLen; modulusLen = (publicKey->bits + 7) / 8; if (inputLen > modulusLen) return (RE_LEN); if (status = RSAPublicBlock (pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey)) return (status); if (pkcsBlockLen != modulusLen) return (RE_LEN); /* Require block type 1. */ if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1)) return (RE_DATA); for (i = 2; i < modulusLen-1; i++) if (pkcsBlock[i] != 0xff) break; /* separator */ if (pkcsBlock[i++] != 0) return (RE_DATA); *outputLen = modulusLen - i; if (*outputLen + 11 > modulusLen) return (RE_DATA); R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock)); return (0); } /* RSA private-key encryption, according to PKCS #1. */ int RSAPrivateEncrypt (output, outputLen, input, inputLen, privateKey) unsigned char *output; /* output block */ unsigned int *outputLen; /* length of output block */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ { int status; unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; unsigned int i, modulusLen; modulusLen = (privateKey->bits + 7) / 8; if (inputLen + 11 > modulusLen) return (RE_LEN); pkcsBlock[0] = 0; /* block type 1 */ pkcsBlock[1] = 1; for (i = 2; i < modulusLen - inputLen - 1; i++) pkcsBlock[i] = 0xff; /* separator */ pkcsBlock[i++] = 0; R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); status = RSAPrivateBlock (output, outputLen, pkcsBlock, modulusLen, privateKey); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock)); return (status); } /* RSA private-key decryption, according to PKCS #1. */ int RSAPrivateDecrypt (output, outputLen, input, inputLen, privateKey) unsigned char *output; /* output block */ unsigned int *outputLen; /* length of output block */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ { int status; unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; unsigned int i, modulusLen, pkcsBlockLen; modulusLen = (privateKey->bits + 7) / 8; if (inputLen > modulusLen) return (RE_LEN); if (status = RSAPrivateBlock (pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey)) return (status); if (pkcsBlockLen != modulusLen) return (RE_LEN); /* Require block type 2. */ if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 2)) return (RE_DATA); for (i = 2; i < modulusLen-1; i++) /* separator */ if (pkcsBlock[i] == 0) break; i++; if (i >= modulusLen) return (RE_DATA); *outputLen = modulusLen - i; if (*outputLen + 11 > modulusLen) return (RE_DATA); R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); /* Zeroize sensitive information. */ R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock)); return (0); } /* Raw RSA public-key operation. Output has same length as modulus. Assumes inputLen < length of modulus. Requires input < modulus. */ static int RSAPublicBlock (output, outputLen, input, inputLen, publicKey) unsigned char *output; /* output block */ unsigned int *outputLen; /* length of output block */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ { NN_DIGIT c[MAX_NN_DIGITS], e[MAX_NN_DIGITS], m[MAX_NN_DIGITS], n[MAX_NN_DIGITS]; unsigned int eDigits, nDigits; NN_Decode (m, MAX_NN_DIGITS, input, inputLen); NN_Decode (n, MAX_NN_DIGITS, publicKey->modulus, MAX_RSA_MODULUS_LEN); NN_Decode (e, MAX_NN_DIGITS, publicKey->exponent, MAX_RSA_MODULUS_LEN); nDigits = NN_Digits (n, MAX_NN_DIGITS); eDigits = NN_Digits (e, MAX_NN_DIGITS); if (NN_Cmp (m, n, nDigits) >= 0) return (RE_DATA); /* Compute c = m^e mod n. */ NN_ModExp (c, m, e, eDigits, n, nDigits); *outputLen = (publicKey->bits + 7) / 8; NN_Encode (output, *outputLen, c, nDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)c, 0, sizeof (c)); R_memset ((POINTER)m, 0, sizeof (m)); return (0); } /* Raw RSA private-key operation. Output has same length as modulus. Assumes inputLen < length of modulus. Requires input < modulus. */ static int RSAPrivateBlock (output, outputLen, input, inputLen, privateKey) unsigned char *output; /* output block */ unsigned int *outputLen; /* length of output block */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ { NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS], dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS], mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS], qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; unsigned int cDigits, nDigits, pDigits; NN_Decode (c, MAX_NN_DIGITS, input, inputLen); NN_Decode (n, MAX_NN_DIGITS, privateKey->modulus, MAX_RSA_MODULUS_LEN); NN_Decode (p, MAX_NN_DIGITS, privateKey->prime[0], MAX_RSA_PRIME_LEN); NN_Decode (q, MAX_NN_DIGITS, privateKey->prime[1], MAX_RSA_PRIME_LEN); NN_Decode (dP, MAX_NN_DIGITS, privateKey->primeExponent[0], MAX_RSA_PRIME_LEN); NN_Decode (dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], MAX_RSA_PRIME_LEN); NN_Decode (qInv, MAX_NN_DIGITS, privateKey->coefficient, MAX_RSA_PRIME_LEN); cDigits = NN_Digits (c, MAX_NN_DIGITS); nDigits = NN_Digits (n, MAX_NN_DIGITS); pDigits = NN_Digits (p, MAX_NN_DIGITS); if (NN_Cmp (c, n, nDigits) >= 0) return (RE_DATA); /* Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. (Assumes q has length at most pDigits, i.e., p > q.) */ NN_Mod (cP, c, cDigits, p, pDigits); NN_Mod (cQ, c, cDigits, q, pDigits); NN_ModExp (mP, cP, dP, pDigits, p, pDigits); NN_AssignZero (mQ, nDigits); NN_ModExp (mQ, cQ, dQ, pDigits, q, pDigits); /* Chinese Remainder Theorem: m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ. */ if (NN_Cmp (mP, mQ, pDigits) >= 0) NN_Sub (t, mP, mQ, pDigits); else { NN_Sub (t, mQ, mP, pDigits); NN_Sub (t, p, t, pDigits); } NN_ModMult (t, t, qInv, p, pDigits); NN_Mult (t, t, q, pDigits); NN_Add (t, t, mQ, nDigits); *outputLen = (privateKey->bits + 7) / 8; NN_Encode (output, *outputLen, t, nDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)c, 0, sizeof (c)); R_memset ((POINTER)cP, 0, sizeof (cP)); R_memset ((POINTER)cQ, 0, sizeof (cQ)); R_memset ((POINTER)dP, 0, sizeof (dP)); R_memset ((POINTER)dQ, 0, sizeof (dQ)); R_memset ((POINTER)mP, 0, sizeof (mP)); R_memset ((POINTER)mQ, 0, sizeof (mQ)); R_memset ((POINTER)p, 0, sizeof (p)); R_memset ((POINTER)q, 0, sizeof (q)); R_memset ((POINTER)qInv, 0, sizeof (qInv)); R_memset ((POINTER)t, 0, sizeof (t)); return (0); } 991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "r_random.h" #include "rsa.h" #include "nn.h" static int RSAPublicBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *)); static int RSAPrivateBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); rsaref/source/nn.c1004440006630000000000003400105567744043011337 037777703401 1 0 /* NN.C - natural numbers routines */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ /* * CHANGES MADE TO THIS FILE UNDER RSAREF license clause 1(c): * * For the MIT PGP 2.6 distribution, this file was modified to permit * replacement of the NN_ModExp routine by an equivalent routine * contained in the PGP 2.6 sources. To enable this change, an #ifdef * was added to this file (search for #ifndef USEMPILIB * below). RSAREF *must* be compiled with USEMPILIB defined for this * change to occur. * * Change made May 21, 1994. */ #include "global.h" #include "rsaref.h" #include "nn.h" #include "digit.h" static NN_DIGIT NN_LShift PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int)); static NN_DIGIT NN_RShift PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int)); static void NN_Div PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); static NN_DIGIT NN_AddDigitMult PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); static NN_DIGIT NN_SubDigitMult PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT)); /* Decodes character string b into a, where character string is ordered from most to least significant. Length: a[digits], b[len]. Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most significant bytes are truncated.) */ void NN_Decode (a, digits, b, len) NN_DIGIT *a; unsigned char *b; unsigned int digits, len; { NN_DIGIT t; int j; unsigned int i, u; for (i = 0, j = len - 1; j >= 0; i++) { t = 0; for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) t |= ((NN_DIGIT)b[j]) << u; a[i] = t; } for (; i < digits; i++) a[i] = 0; } /* Encodes b into character string a, where character string is ordered from most to least significant. Lengths: a[len], b[digits]. Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant digits are truncated.) */ void NN_Encode (a, len, b, digits) NN_DIGIT *b; unsigned char *a; unsigned int digits, len; { NN_DIGIT t; int j; unsigned int i, u; for (i = 0, j = len - 1; i < digits; i++) { t = b[i]; for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) a[j] = (unsigned char)(t >> u); } for (; j >= 0; j--) a[j] = 0; } /* Assigns a = 0. Lengths: a[digits], b[digits]. */ void NN_Assign (a, b, digits) NN_DIGIT *a, *b; unsigned int digits; { unsigned int i; for (i = 0; i < digits; i++) a[i] = b[i]; } /* Assigns a = 0. Lengths: a[digits]. */ void NN_AssignZero (a, digits) NN_DIGIT *a; unsigned int digits; { unsigned int i; for (i = 0; i < digits; i++) a[i] = 0; } /* Assigns a = 2^b. Lengths: a[digits]. Requires b < digits * NN_DIGIT_BITS. */ void NN_Assign2Exp (a, b, digits) NN_DIGIT *a; unsigned int b, digits; { NN_AssignZero (a, digits); if (b >= digits * NN_DIGIT_BITS) return; a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS); } /* Computes a = b + c. Returns carry. Lengths: a[digits], b[digits], c[digits]. */ NN_DIGIT NN_Add (a, b, c, digits) NN_DIGIT *a, *b, *c; unsigned int digits; { NN_DIGIT ai, carry; unsigned int i; carry = 0; for (i = 0; i < digits; i++) { if ((ai = b[i] + carry) < carry) ai = c[i]; else if ((ai += c[i]) < c[i]) carry = 1; else carry = 0; a[i] = ai; } return (carry); } /* Computes a = b - c. Returns borrow. Lengths: a[digits], b[digits], c[digits]. */ NN_DIGIT NN_Sub (a, b, c, digits) NN_DIGIT *a, *b, *c; unsigned int digits; { NN_DIGIT ai, borrow; unsigned int i; borrow = 0; for (i = 0; i < digits; i++) { if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) ai = MAX_NN_DIGIT - c[i]; else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i])) borrow = 1; else borrow = 0; a[i] = ai; } return (borrow); } /* Computes a = b * c. Lengths: a[2*digits], b[digits], c[digits]. Assumes digits < MAX_NN_DIGITS. */ void NN_Mult (a, b, c, digits) NN_DIGIT *a, *b, *c; unsigned int digits; { NN_DIGIT t[2*MAX_NN_DIGITS]; unsigned int bDigits, cDigits, i; NN_AssignZero (t, 2 * digits); bDigits = NN_Digits (b, digits); cDigits = NN_Digits (c, digits); for (i = 0; i < bDigits; i++) t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits); NN_Assign (a, t, 2 * digits); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)t, 0, sizeof (t)); } /* Computes a = b mod c. Lengths: a[cDigits], b[bDigits], c[cDigits]. Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS. */ void NN_Mod (a, b, bDigits, c, cDigits) NN_DIGIT *a, *b, *c; unsigned int bDigits, cDigits; { NN_DIGIT t[2 * MAX_NN_DIGITS]; NN_Div (t, a, b, bDigits, c, cDigits); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)t, 0, sizeof (t)); } /* Computes a = b * c mod d. Lengths: a[digits], b[digits], c[digits], d[digits]. Assumes d > 0, digits < MAX_NN_DIGITS. */ void NN_ModMult (a, b, c, d, digits) NN_DIGIT *a, *b, *c, *d; unsigned int digits; { NN_DIGIT t[2*MAX_NN_DIGITS]; NN_Mult (t, b, c, digits); NN_Mod (a, t, 2 * digits, d, digits); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)t, 0, sizeof (t)); } /* * PGP 2.6's mpilib contains a faster modular exponentiation routine, * mp_modexp. If USEMPILIB is defined, NN_ModExp is replaced in the * PGP 2.6 sources with a stub call to mp_modexp. If USEMPILIB is * not defined, we'll get a pure (albeit slower) RSAREF * implementation. * * The RSAREF license, clause 1(c), permits "...modify[ing] the * Program in any manner for porting or performance improvement * purposes..." */ #ifndef USEMPILIB /* Computes a = b^c mod d. Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. Assumes b < d, d > 0, cDigits > 0, dDigits > 0, dDigits < MAX_NN_DIGITS. */ void NN_ModExp (a, b, c, cDigits, d, dDigits) NN_DIGIT *a, *b, *c, *d; unsigned int cDigits, dDigits; { NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS]; int i; unsigned int ciBits, j, s; /* Store b, b^2 mod d, and b^3 mod d. */ NN_Assign (bPower[0], b, dDigits); NN_ModMult (bPower[1], bPower[0], b, d, dDigits); NN_ModMult (bPower[2], bPower[1], b, d, dDigits); NN_ASSIGN_DIGIT (t, 1, dDigits); cDigits = NN_Digits (c, cDigits); for (i = cDigits - 1; i >= 0; i--) { ci = c[i]; ciBits = NN_DIGIT_BITS; /* Scan past leading zero bits of most significant digit. */ if (i == (int)(cDigits - 1)) { while (! DIGIT_2MSB (ci)) { ci <<= 2; ciBits -= 2; } } for (j = 0; j < ciBits; j += 2, ci <<= 2) { /* Compute t = t^4 * b^s mod d, where s = two MSB's of d. */ NN_ModMult (t, t, t, d, dDigits); NN_ModMult (t, t, t, d, dDigits); if (s = DIGIT_2MSB (ci)) NN_ModMult (t, t, bPower[s-1], d, dDigits); } } NN_Assign (a, t, dDigits); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)bPower, 0, sizeof (bPower)); R_memset ((POINTER)t, 0, sizeof (t)); } #endif /* Compute a = 1/b mod c, assuming inverse exists. Lengths: a[digits], b[digits], c[digits]. Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS. */ void NN_ModInv (a, b, c, digits) NN_DIGIT *a, *b, *c; unsigned int digits; { NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS], u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS], v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS]; int u1Sign; /* Apply extended Euclidean algorithm, modified to avoid negative numbers. */ NN_ASSIGN_DIGIT (u1, 1, digits); NN_AssignZero (v1, digits); NN_Assign (u3, b, digits); NN_Assign (v3, c, digits); u1Sign = 1; while (! NN_Zero (v3, digits)) { NN_Div (q, t3, u3, digits, v3, digits); NN_Mult (w, q, v1, digits); NN_Add (t1, u1, w, digits); NN_Assign (u1, v1, digits); NN_Assign (v1, t1, digits); NN_Assign (u3, v3, digits); NN_Assign (v3, t3, digits); u1Sign = -u1Sign; } /* Negate result if sign is negative. */ if (u1Sign < 0) NN_Sub (a, c, u1, digits); else NN_Assign (a, u1, digits); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)q, 0, sizeof (q)); R_memset ((POINTER)t1, 0, sizeof (t1)); R_memset ((POINTER)t3, 0, sizeof (t3)); R_memset ((POINTER)u1, 0, sizeof (u1)); R_memset ((POINTER)u3, 0, sizeof (u3)); R_memset ((POINTER)v1, 0, sizeof (v1)); R_memset ((POINTER)v3, 0, sizeof (v3)); R_memset ((POINTER)w, 0, sizeof (w)); } /* Computes a = gcd(b, c). Lengths: a[digits], b[digits], c[digits]. Assumes b > c, digits < MAX_NN_DIGITS. */ void NN_Gcd (a, b, c, digits) NN_DIGIT *a, *b, *c; unsigned int digits; { NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS]; NN_Assign (u, b, digits); NN_Assign (v, c, digits); while (! NN_Zero (v, digits)) { NN_Mod (t, u, digits, v, digits); NN_Assign (u, v, digits); NN_Assign (v, t, digits); } NN_Assign (a, u, digits); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)t, 0, sizeof (t)); R_memset ((POINTER)u, 0, sizeof (u)); R_memset ((POINTER)v, 0, sizeof (v)); } /* Returns sign of a - b. Lengths: a[digits], b[digits]. */ int NN_Cmp (a, b, digits) NN_DIGIT *a, *b; unsigned int digits; { int i; for (i = digits - 1; i >= 0; i--) { if (a[i] > b[i]) return (1); if (a[i] < b[i]) return (-1); } return (0); } /* Returns nonzero iff a is zero. Lengths: a[digits]. */ int NN_Zero (a, digits) NN_DIGIT *a; unsigned int digits; { unsigned int i; for (i = 0; i < digits; i++) if (a[i]) return (0); return (1); } /* Returns the significant length of a in bits. Lengths: a[digits]. */ unsigned int NN_Bits (a, digits) NN_DIGIT *a; unsigned int digits; { if ((digits = NN_Digits (a, digits)) == 0) return (0); return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1])); } /* Returns the significant length of a in digits. Lengths: a[digits]. */ unsigned int NN_Digits (a, digits) NN_DIGIT *a; unsigned int digits; { int i; for (i = digits - 1; i >= 0; i--) if (a[i]) break; return (i + 1); } /* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. Lengths: a[digits], b[digits]. Requires c < NN_DIGIT_BITS. */ static NN_DIGIT NN_LShift (a, b, c, digits) NN_DIGIT *a, *b; unsigned int c, digits; { NN_DIGIT bi, carry; unsigned int i, t; if (c >= NN_DIGIT_BITS) return (0); t = NN_DIGIT_BITS - c; carry = 0; for (i = 0; i < digits; i++) { bi = b[i]; a[i] = (bi << c) | carry; carry = c ? (bi >> t) : 0; } return (carry); } /* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. Lengths: a[digits], b[digits]. Requires: c < NN_DIGIT_BITS. */ static NN_DIGIT NN_RShift (a, b, c, digits) NN_DIGIT *a, *b; unsigned int c, digits; { NN_DIGIT bi, carry; int i; unsigned int t; if (c >= NN_DIGIT_BITS) return (0); t = NN_DIGIT_BITS - c; carry = 0; for (i = digits - 1; i >= 0; i--) { bi = b[i]; a[i] = (bi >> c) | carry; carry = c ? (bi << t) : 0; } return (carry); } /* Computes a = c div d and b = c mod d. Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, dDigits < MAX_NN_DIGITS. */ static void NN_Div (a, b, c, cDigits, d, dDigits) NN_DIGIT *a, *b, *c, *d; unsigned int cDigits, dDigits; { NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t; int i; unsigned int ddDigits, shift; ddDigits = NN_Digits (d, dDigits); if (ddDigits == 0) return; /* Normalize operands. */ shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); NN_AssignZero (cc, ddDigits); cc[cDigits] = NN_LShift (cc, c, shift, cDigits); NN_LShift (dd, d, shift, ddDigits); t = dd[ddDigits-1]; NN_AssignZero (a, cDigits); for (i = cDigits-ddDigits; i >= 0; i--) { /* Underestimate quotient digit and subtract. */ if (t == MAX_NN_DIGIT) ai = cc[i+dDigits]; else NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1); cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits); /* Correct estimate. */ while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { ai++; cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); } a[i] = ai; } /* Restore result. */ NN_AssignZero (b, dDigits); NN_RShift (b, cc, shift, ddDigits); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)cc, 0, sizeof (cc)); R_memset ((POINTER)dd, 0, sizeof (dd)); } /* Computes a = b + c*d, where c is a digit. Returns carry. Lengths: a[digits], b[digits], d[digits]. */ static NN_DIGIT NN_AddDigitMult (a, b, c, d, digits) NN_DIGIT *a, *b, c, *d; unsigned int digits; { NN_DIGIT carry, t[2]; unsigned int i; if (c == 0) return (0); carry = 0; for (i = 0; i < digits; i++) { NN_DigitMult (t, c, d[i]); if ((a[i] = b[i] + carry) < carry) carry = 1; else carry = 0; if ((a[i] += t[0]) < t[0]) carry++; carry += t[1]; } return (carry); } /* Computes a = b - c*d, where c is a digit. Returns borrow. Lengths: a[digits], b[digits], d[digits]. */ static NN_DIGIT NN_SubDigitMult (a, b, c, d, digits) NN_DIGIT *a, *b, c, *d; unsigned int digits; { NN_DIGIT borrow, t[2]; unsigned int i; if (c == 0) return (0); borrow = 0; for (i = 0; i < digits; i++) { NN_DigitMult (t, c, d[i]); if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) borrow = 1; else borrow = 0; if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0])) borrow++; borrow += t[1]; } return (borrow); } /* Returns the significant length of a in bits, where a is a digit. */ static unsigned int NN_DigitBits (a) NN_DIGIT a; { unsigned int i; for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1) if (a == 0) break; return (i); } ts], c[digits]. Assumes digits < MAX_NN_DIGITS. */ void NN_Mult (a, b, c, digits) NN_DIGIT *a, *b, *c; unsigned int digits; { NN_DIGIT t[2*MAX_NN_DIGITS]; unsigned int bDigits, cDigits, i; NN_AssignZero (t, 2 * digits); bDigits = NN_Digits (b, digits); cDigits = NN_Digits (c, digits); for (i = 0; i < bDigits; i++) t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits); NN_Assign (a, t, 2 * digits); /* Zeroize potentially sensitive information. */ R_memset (rsaref/source/r_encode.h1004440006630000000000000055305153737443012511 037777703401 1 0 /* R_ENCODE.H - header file for R_ENCODE.C */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ void R_EncodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int)); int R_DecodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int)); * PGP 2.6's mpilib contains a faster modular exponentiation routine, * mp_modexp. If USEMPILIB is defined, NN_ModExp is replaced in the * PGP 2.6 rsaref/source/rsaref.h1004440006630000000000001121705600704473012206 037777703401 1 0 /* RSAREF.H - header file for RSAREF cryptographic toolkit */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ /* Message-digest algorithms. */ #define DA_MD2 3 #define DA_MD5 5 /* RSA key lengths. */ #define MIN_RSA_MODULUS_BITS 508 #define MAX_RSA_MODULUS_BITS 2048 #define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8) #define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2) #define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8) /* Maximum lengths of encoded and encrypted content, as a function of content length len. Also, inverse functions. */ #define ENCODED_CONTENT_LEN(len) (4*(len)/3 + 3) #define ENCRYPTED_CONTENT_LEN(len) ENCODED_CONTENT_LEN ((len)+8) #define DECODED_CONTENT_LEN(len) (3*(len)/4 + 1) #define DECRYPTED_CONTENT_LEN(len) DECODED_CONTENT_LEN ((len)-1) /* Maximum lengths of signatures, encrypted keys, encrypted signatures, and message digests. */ #define MAX_SIGNATURE_LEN MAX_RSA_MODULUS_LEN #define MAX_PEM_SIGNATURE_LEN ENCODED_CONTENT_LEN (MAX_SIGNATURE_LEN) #define MAX_PEM_ENCRYPTED_KEY_LEN ENCODED_CONTENT_LEN (MAX_RSA_MODULUS_LEN) #define MAX_PEM_ENCRYPTED_SIGNATURE_LEN \ ENCRYPTED_CONTENT_LEN (MAX_SIGNATURE_LEN) #define MAX_DIGEST_LEN 16 /* Error codes. */ #define RE_CONTENT_ENCODING 0x0400 #define RE_DATA 0x0401 #define RE_DIGEST_ALGORITHM 0x0402 #define RE_ENCODING 0x0403 #define RE_KEY 0x0404 #define RE_KEY_ENCODING 0x0405 #define RE_LEN 0x0406 #define RE_MODULUS_LEN 0x0407 #define RE_NEED_RANDOM 0x0408 #define RE_PRIVATE_KEY 0x0409 #define RE_PUBLIC_KEY 0x040a #define RE_SIGNATURE 0x040b #define RE_SIGNATURE_ENCODING 0x040c /* Random structure. */ typedef struct { unsigned int bytesNeeded; unsigned char state[16]; unsigned int outputAvailable; unsigned char output[16]; } R_RANDOM_STRUCT; /* RSA public and private 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; 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; /* RSA prototype key. */ typedef struct { unsigned int bits; /* length in bits of modulus */ int useFermat4; /* public exponent (1 = F4, 0 = 3) */ } R_RSA_PROTO_KEY; /* Random structures. */ int R_RandomInit PROTO_LIST ((R_RANDOM_STRUCT *)); int R_RandomUpdate PROTO_LIST ((R_RANDOM_STRUCT *, unsigned char *, unsigned int)); int R_GetRandomBytesNeeded PROTO_LIST ((unsigned int *, R_RANDOM_STRUCT *)); void R_RandomFinal PROTO_LIST ((R_RANDOM_STRUCT *)); /* Cryptographic enhancements. */ int R_SignPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, unsigned char *, unsigned int, int, int, R_RSA_PRIVATE_KEY *)); int R_VerifyPEMSignature PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, unsigned char *, unsigned int, int, int, R_RSA_PUBLIC_KEY *)); int R_VerifyBlockSignature PROTO_LIST ((unsigned char *, unsigned int, unsigned char *, unsigned int, int, R_RSA_PUBLIC_KEY *)); int R_SealPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, unsigned char *, unsigned int *, unsigned char [8], unsigned char *, unsigned int, int, R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, R_RANDOM_STRUCT *)); int R_OpenPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned char [8], int, R_RSA_PRIVATE_KEY *, R_RSA_PUBLIC_KEY *)); int R_DigestBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int)); /* Key-pair generation. */ int R_GeneratePEMKeys PROTO_LIST ((R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, R_RSA_PROTO_KEY *, R_RANDOM_STRUCT *)); /* Routines supplied by the implementor. */ void R_memset PROTO_LIST ((POINTER, int, unsigned int)); void R_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); int R_memcmp PROTO_LIST ((POINTER, POINTER, unsigned int)); bi = b[i]; a[i] = (bi << c) | carry; carry = c ? (bi >> t) : 0; } return (carry); } /* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. Lengths: a[digits], b[digits]. Requires: c < NN_DIGIT_BITS. */ static NN_DIGIT NN_RShift (a, b, c, digits) NN_DIGIT *a, *b; unsigned int c, digits; { NN_DIGIT bi, carry; int i; unsigrsaref/source/md2.h1004440006630000000000000236405153737447011423 037777703401 1 0 /* MD2.H - header file for MD2C.C */ /* Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted for non-commercial Internet Privacy-Enhanced Mail provided that it is identified as the "RSA Data Security, Inc. MD2 Message Digest Algorithm" in all material mentioning or referencing this software or this function. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ 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; void MD2Init PROTO_LIST ((MD2_CTX *)); void MD2Update PROTO_LIST ((MD2_CTX *, unsigned char *, unsigned int)); void MD2Final PROTO_LIST ((unsigned char [16], MD2_CTX *)); Lengths: a[digits], b[digits], d[digits]. */ static NN_DIGIT NN_AddDigitMult (a, b, c, d, digits) NN_DIGIT *a, *b, c, *d; unsigned int digits; { NN_DIGIT carry, t[2]; unsigned int i; if (c == 0) return (0); carry = 0; for (i = 0; i < digits; i++) { rsaref/source/r_encode.c1004440006630000000000001703205153737451012503 037777703401 1 0 /* R_ENCODE.H - RFC 1113 encoding and decoding routines */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ #include "global.h" #include "rsaref.h" #include "r_encode.h" /* RFC 1113 encoding: Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y */ #define ENCODING(i) \ (unsigned char)(((i) < 26) ? ((i) + 0x41) : \ (((i) < 52) ? ((i) - 26 + 0x61) : \ (((i) < 62) ? ((i) - 52 + 0x30) : \ (((i) == 62) ? 0x2b : 0x2f)))) #define ENCODING_PAD 0x3d #define IS_ENCODING(c) \ ((((c) >= 0x41) && ((c) <= 0x5a)) || \ (((c) >= 0x61) && ((c) <= 0x7a)) || \ (((c) >= 0x30) && ((c) <= 0x39)) || \ ((c) == 0x2b) || \ ((c) == 0x2f)) /* assumes IS_ENCODING (c) == 1 */ #define DECODING(c) \ (((c) == 0x2b) ? 62 : \ (((c) == 0x2f) ? 63 : \ (((c) <= 0x39) ? ((c) - 0x30 + 52) : \ (((c) <= 0x5a) ? ((c) - 0x41) : ((c) - 0x61 + 26))))) static void EncodeQuantum PROTO_LIST ((unsigned char [4], unsigned char [3])); static int DecodeQuantum PROTO_LIST ((unsigned char [3], unsigned char [4])); static void EncodeLastQuantum PROTO_LIST ((unsigned char [4], unsigned char *, unsigned int)); static int DecodeLastQuantum PROTO_LIST ((unsigned char *, unsigned int *, unsigned char [4])); void R_EncodePEMBlock (encodedBlock, encodedBlockLen, block, blockLen) unsigned char *encodedBlock; /* encoded block */ unsigned int *encodedBlockLen; /* length of encoded block */ unsigned char *block; /* block */ unsigned int blockLen; /* length of block */ { unsigned int i, lastLen; if (blockLen < 1) { *encodedBlockLen = 0; return; } for (i = 0; i < (blockLen-1)/3; i++) EncodeQuantum (&encodedBlock[4*i], &block[3*i]); lastLen = blockLen - 3*i; EncodeLastQuantum (&encodedBlock[4*i], &block[3*i], lastLen); *encodedBlockLen = 4*i + 4; } int R_DecodePEMBlock (block, blockLen, encodedBlock, encodedBlockLen) unsigned char *block; /* block */ unsigned int *blockLen; /* length of block */ unsigned char *encodedBlock; /* encoded block */ unsigned int encodedBlockLen; /* length of encoded block */ { int status; unsigned int i, lastLen; if (encodedBlockLen % 4) return (RE_ENCODING); if (encodedBlockLen < 1) { *blockLen = 0; return (0); } for (i = 0; i < (encodedBlockLen-1)/4; i++) if (status = DecodeQuantum (&block[3*i], &encodedBlock[4*i])) return (status); if (status = DecodeLastQuantum (&block[3*i], &lastLen, &encodedBlock[4*i])) return (status); *blockLen = 3*i + lastLen; return (0); } static void EncodeQuantum (encodedQuantum, quantum) unsigned char encodedQuantum[4]; unsigned char quantum[3]; { UINT4 temp; unsigned int a, b, c, d; temp = ((UINT4)quantum[0]) << 16; temp |= ((UINT4)quantum[1]) << 8; temp |= (UINT4)quantum[2]; a = (unsigned int)((temp >> 18) & 0x3f); b = (unsigned int)((temp >> 12) & 0x3f); c = (unsigned int)((temp >> 6) & 0x3f); d = (unsigned int)(temp & 0x3f); encodedQuantum[0] = ENCODING (a); encodedQuantum[1] = ENCODING (b); encodedQuantum[2] = ENCODING (c); encodedQuantum[3] = ENCODING (d); /* Zeroize potentially sensitive information. */ temp = 0; a = b = c = d = 0; } static int DecodeQuantum (quantum, encodedQuantum) unsigned char quantum[3]; unsigned char encodedQuantum[4]; { UINT4 temp; unsigned int a, b, c, d; if (! IS_ENCODING (encodedQuantum[0]) || ! IS_ENCODING (encodedQuantum[1]) || ! IS_ENCODING (encodedQuantum[2]) || ! IS_ENCODING (encodedQuantum[3])) return (RE_ENCODING); a = DECODING (encodedQuantum[0]); b = DECODING (encodedQuantum[1]); c = DECODING (encodedQuantum[2]); d = DECODING (encodedQuantum[3]); temp = ((UINT4)a) << 18; temp |= ((UINT4)b) << 12; temp |= ((UINT4)c) << 6; temp |= (UINT4)d; quantum[0] = (unsigned char)(temp >> 16); quantum[1] = (unsigned char)(temp >> 8); quantum[2] = (unsigned char)temp; /* Zeroize potentially sensitive information. */ temp = 0; a = b = c = d = 0; return (0); } static void EncodeLastQuantum (encodedQuantum, quantum, quantumLen) unsigned char encodedQuantum[4]; unsigned char *quantum; unsigned int quantumLen; /* 1, 2 or 3 */ { UINT4 temp; unsigned int a, b, c, d; temp = ((UINT4)quantum[0]) << 16; if (quantumLen >= 2) temp |= ((UINT4)quantum[1]) << 8; if (quantumLen == 3) temp |= ((UINT4)quantum[2]); a = (unsigned int)((temp >> 18) & 0x3f); b = (unsigned int)((temp >> 12) & 0x3f); if (quantumLen >= 2) c = (unsigned int)((temp >> 6) & 0x3f); if (quantumLen == 3) d = (unsigned int)(temp & 0x3f); encodedQuantum[0] = ENCODING (a); encodedQuantum[1] = ENCODING (b); if (quantumLen >= 2) encodedQuantum[2] = ENCODING (c); else encodedQuantum[2] = ENCODING_PAD; if (quantumLen == 3) encodedQuantum[3] = ENCODING (d); else encodedQuantum[3] = ENCODING_PAD; /* Zeroize potentially sensitive information. */ temp = 0; a = b = c = d = 0; } static int DecodeLastQuantum (quantum, quantumLen, encodedQuantum) unsigned char *quantum; unsigned int *quantumLen; /* 1, 2 or 3 */ unsigned char encodedQuantum[4]; { UINT4 temp; unsigned int a, b, c, d; if (! IS_ENCODING (encodedQuantum[0]) || ! IS_ENCODING (encodedQuantum[1]) || (! IS_ENCODING (encodedQuantum[2]) && (encodedQuantum[2] != ENCODING_PAD)) || (! IS_ENCODING (encodedQuantum[3]) && (encodedQuantum[3] != ENCODING_PAD))) return (RE_ENCODING); if (encodedQuantum[2] == ENCODING_PAD) *quantumLen = 1; else if (encodedQuantum[3] == ENCODING_PAD) *quantumLen = 2; else *quantumLen = 3; a = DECODING (encodedQuantum[0]); b = DECODING (encodedQuantum[1]); if (*quantumLen >= 2) c = DECODING (encodedQuantum[2]); if (*quantumLen == 3) d = DECODING (encodedQuantum[3]); temp = ((UINT4)a) << 18; temp |= ((UINT4)b) << 12; if (*quantumLen >= 2) temp |= ((UINT4)c) << 6; if (*quantumLen == 3) temp |= ((UINT4)d); quantum[0] = (unsigned char)(temp >> 16); if (*quantumLen >= 2) quantum[1] = (unsigned char)(temp >> 8); if (*quantumLen == 3) quantum[2] = (unsigned char)temp; /* Zeroize potentially sensitive information. */ temp = 0; a = b = c = d = 0; return (0); } 1004440006630000000000000236405153737447011423 037777703401 1 0 rsaref/test/0407750006630000000000000000005626264754007474 5 0 1 0 rsaref/test/global.h1006440006630000000000000161405153737513011651 037777703401 1 0 /* GLOBAL.H - RSAREF types and constants */ /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. */ /* PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping. The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 #endif /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ typedef unsigned long int UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif rsaref/test/512sig.md21006440006630000000000000013005153737465011654 037777703401 1 0 kKe/Lotco5wvTsad5dekRvQs8AwJ6YeB6MYfC9jztZGbooClJwqBMHoSuPQ9hRah9vubvxvsexms7d0vQOhYcg== 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t rsaref/test/512test.in1006440006630000000000000012005153737466011775 037777703401 1 0 v n signfile 512sig 1 o 512env 512env.sig 512env.key 512env.iv 2 1 512env.out q x61) && ((c) <= 0x7a)) || \ (((c) >= 0x30) && ((c) <= 0x39)) || \ ((c) == 0x2b) || \ ((c) == 0x2f)) /* assumes IS_ENCODING (c) == 1 */ #define DECODING(c) \ (((c) == 0x2b) ? 62 : \ (((c) == 0x2f) ? 63 : \ (((c) <= 0x39) ? ((c) - 0x30 + 52) : \ (((c) <= 0x5a) ? ((c) - 0x41) : ((c) - 0x61 + 26))))) static void EncodeQuantum PROTO_LIST ((unsigned char [4], unsigned char [3])); static int DecodeQuantumrsaref/test/767test.in1006440006630000000000000014105153737467012015 037777703401 1 0 g 767 767key.out v n signfile 767sig 3 o 767env 767env.sig 767env.key 767env.iv 2 3 767env.out q /* length of block */ { unsigned int i, lastLen; if (blockLen < 1) { *encodedBlockLen = 0; return; } for (i = 0; i < (blockLen-1)/3; i++) EncodeQuantum (&encodedBlock[4*i], &block[3*i]); lastLen = blockLen - 3*i; EncodeLastQuantum (&encodedBlock[4*i], &block[3*i], lastLen); *encodedBlockLen = 4*i + 4; } int R_DecodePEMBlock (block, blockLen, encodedBlrsaref/test/508test.in1006440006630000000000000014105153737467012006 037777703401 1 0 g 508 508key.out v n signfile 508sig 3 o 508env 508env.sig 508env.key 508env.iv 2 3 508env.out q lock[4*i])) return (status); if (status = DecodeLastQuantum (&block[3*i], &lastLen, &encodedBlock[4*i])) return (status); *blockLen = 3*i + lastLen; return (0); } static void EncodeQuantum (encodedQuantum, quantum) unsigned char encodedQuantum[4]; unsigned char quantum[3]; { UINT4 temp; unsigned int a, b, c, d; temp = ((UINT4)quantum[0]) << 16; temp |= ((UINT4)quantum[1]) << 8; rsaref/test/1024test.in1006440006630000000000000015105153737470012053 037777703401 1 0 g 1024 1024key.out v n signfile 1024sig 3 o 1024env 1024env.sig 1024env.key 1024env.iv 2 3 1024env.out q antum[0]) || ! IS_ENCODING (encodedQuantum[1]) || ! IS_ENCODING (encodedQuantum[2]) || ! IS_ENCODING (encodedQuantum[3])) return (RE_ENCODING); a = DECODING (encodedQuantum[0]); b = DECODING (encodedQuantum[1]); c = DECODING (encodedQuantum[2]); d = DECODING (encodedQuantum[3]); temp = ((UINT4)a) << 18; temp |= ((UINT4)b) << 12; temp |= ((UINT4)c) << 6; temp |=rsaref/test/1024env.sig1006440006630000000000000014005153737471012037 037777703401 1 0 kIfje468W/mZ1ZUAGFcH1xbxVuo7ihO8SlZkuqrToIywvMPcX4NjGwZ0UpHn4u5Aoh4Kk2vzFpoXfPFG+fwkGcO+pmICo1Nd3) temp |= ((UINT4)quantum[2]); a = (unsigned int)((temp >> 18) & 0x3f); b = (unsigned int)((temp >> 12) & 0x3f); if (quantumLen >= 2) c = (unsigned int)((temp >> 6) & 0x3f); if (quantumLen == 3) d = (unsigned int)(temp & 0x3f); encodedQuantum[0] = ENCODING (a); encodedQuantum[1] = ENCODING (b); if (quantumLen >= 2) encodedQuantum[2] = ENCODING (c); else encodedQuantum[2] =rsaref/test/1024env.key1006440006630000000000000025405153737472012054 037777703401 1 0 mgHGroukTY8V0CvVs4RGWEX4Riq7MakhDW8z8o+GgHVe5WppCqpH0RZxKzrhXRY1VpaE0Y656LqvyRwZ6wJR/I82Ng4ZV3GHhh9ICd2KLZ3Gj54XHdIF9X6NAwrREKupTRyrLc+mJLMkGiIEsV8zP6Pamlsgh/3AX71swPZ/JZ0= (encodedQuantum[3] != ENCODING_PAD))) return (RE_ENCODING); if (encodedQuantum[2] == ENCODING_PAD) *quantumLen = 1; else if (encodedQuantum[3] == ENCODING_PAD) *quantumLen = 2; else *quantumLen = 3; a = DECODING (encodedQuantum[0]); b = DECODING (encodedQuantum[1]); if (*quantumLen >= 2) c rsaref/test/1024env.iv1006440006630000000000000001005153737472011670 037777703401 1 0 ­[ï¶" return (0); } 1004440006630000000000000236405153737447011423 037777703401 1 0 rsaref/test/1024env1006440006630000000000000037005153737473011265 037777703401 1 0 tKg4dSO19iDK+iPHWEviWURaG0hBW8LHH6L5jBmpjFdIPTOBvE2/i52DRF0Bk7yTHyVtyCIcT7aKg8MODBRLW2ZkAIXdhQkMBWbRHBf3b4tag00iGLfmSg4sILyx9YsGuAr3+c/xV/H3R9ZE9KnpD6+mJa61zq7YQkYRVz8g5ZSHRsyfc2Dq2ZRUnIbxJKpCbZN2BAv9rQOJfqPKOlpGOEDyNB+aFMg7IqqBsW2NZkaoAcmXZwhjdg==37777703401 1 0 rsaref/test/508key1006440006630000000000000237005153737474011216 037777703401 1 0 Public Key, 508 bits: modulus: 0c 22 c2 61 ed 7c 06 0d 87 e2 5c 5d a8 7a 92 0e 8b 2a 7e c5 02 bd 51 ef a6 09 b0 a8 d7 ae bb 28 a7 dc c4 12 48 16 2b 60 4c 0c 58 a3 4c 76 4d b4 7a 19 7b d2 f7 3c aa 8e 78 45 7e 4c a3 90 6d 6d exponent: 01 00 01 Private Key, 508 bits: modulus: 0c 22 c2 61 ed 7c 06 0d 87 e2 5c 5d a8 7a 92 0e 8b 2a 7e c5 02 bd 51 ef a6 09 b0 a8 d7 ae bb 28 a7 dc c4 12 48 16 2b 60 4c 0c 58 a3 4c 76 4d b4 7a 19 7b d2 f7 3c aa 8e 78 45 7e 4c a3 90 6d 6d public exponent: 01 00 01 exponent: 0b 73 68 d2 9a 10 e2 6d 36 00 42 83 25 0b b2 71 02 a3 30 46 98 95 26 90 e7 ac 51 02 9f b0 81 6c 2b 1a 1f a4 cc 07 be 7c b5 5b 07 4b 9c d0 88 a0 9b 69 6a c6 9f a6 f9 b4 59 7e 83 82 22 64 1e c1 prime 1: 3f 5e 6e e1 c3 ea 31 41 90 e0 8e 24 47 5e b8 16 f1 21 1e d1 49 ff 95 33 e5 60 de 4c ae ae f7 29 prime 2: 31 06 cd d0 08 c9 15 09 14 93 8a 8c a5 d7 84 b8 56 15 42 38 b7 e7 8e 89 cb d6 56 9f 59 76 20 a5 prime exponent 1: 38 3b e7 0e 36 3b a7 86 55 b8 d0 aa e5 22 eb 1e 80 d1 31 75 ec c3 00 76 d3 41 49 44 a7 67 e1 31 prime exponent 2: 21 92 75 31 76 32 ac 72 f1 62 2f 48 2c f0 ae 73 c4 8e fe 2f f4 cf 5e 2e 42 25 5e 5f f4 55 0d f9 coefficient: 05 01 de 11 43 40 4e 1c 35 01 49 f9 24 94 a3 34 15 64 cd 47 29 89 e4 38 95 67 ea 9d 8d 99 79 ea Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t rsaref/test/767env.sig1006440006630000000000000014005153737474011777 037777703401 1 0 F4lTy9YJNBKS0XpVKiUje8curEsX++hHJRF6/yhhDDLg2uWf8+6+Itl5u95xvX/kpgII3cxrPd0IFHx5IvZZ2c5cBcI4753o0x7a)) || \ (((c) >= 0x30) && ((c) <= 0x39)) || \ ((c) == 0x2b) || \ ((c) == 0x2f)) /* assumes IS_ENCODING (c) == 1 */ #define DECODING(c) \ (((c) == 0x2b) ? 62 : \ (((c) == 0x2f) ? 63 : \ (((c) <= 0x39) ? ((c) - 0x30 + 52) : \ (((c) <= 0x5a) ? ((c) - 0x41) : ((c) - 0x61 + 26))))) static void EncodeQuantum PROTO_LIST ((unsigned char [4], unsigned char [3])); static int DecodeQuantumrsaref/test/767env.key1006440006630000000000000020005153737475012003 037777703401 1 0 VukbYzQ3Ss2ceYzWLrg+CUkpdxqULSuayHVVabrhRmQcYCSiVryKlk65ehSLlvy9kWI5oBNx+wbYm7TWNESpvX8pyhzAjAJAYhSrOfxPF+yihCFeJ4UYE2RCfjZPfBJy unsigned int i, lastLen; if (blockLen < 1) { *encodedBlockLen = 0; return; } for (i = 0; i < (blockLen-1)/3; i++) EncodeQuantum (&encodedBlock[4*i], &block[3*i]); lastLen = blockLen - 3*i; EncodeLastQuantum (&encodedBlock[4*i], &block[3*i], lastLen); *encodedBlockLen = 4*i + 4; } int R_DecodePEMBlock (block, blockLen, encodedBlrsaref/test/767env.iv1006440006630000000000000001005153737476011631 037777703401 1 0 ît’Ç’‘p8key.out v n signfile 508sig 3 o 508env 508env.sig 508env.key 508env.iv 2 3 508env.out q lock[4*i])) return (status); if (status = DecodeLastQuantum (&block[3*i], &lastLen, &encodedBlock[4*i])) return (status); *blockLen = 3*i + lastLen; return (0); } static void EncodeQuantum (encodedQuantum, quantum) unsigned char encodedQuantum[4]; unsigned char quantum[3]; { UINT4 temp; unsigned int a, b, c, d; temp = ((UINT4)quantum[0]) << 16; temp |= ((UINT4)quantum[1]) << 8; rsaref/test/767env1006440006630000000000000037005153737476011225 037777703401 1 0 adG3UGHzcaeS6zkY3JeUVGNuP0gN4D1CUK3mFiPdTA/nvD0HLNYE0raWvC2C7S47n80pUAwWI03TG+cHuBFF1YwZWQIKuaGY5c6n6Dx4PP/gjaO58yyb6+9SeKrGGzB8I/HwFeCfQJvsbi9hRzLXhArCPCpsatpeBgg0TonWmR1eGdChizS39oJOFcdIkwvK6QSTJNiMjFxYPkN2X16g5cS3bt3tM6D3Hdf5qZTuu0Kq9f8b191t/Q== return (RE_ENCODING); a = DECODING (encodedQuantum[0]); b = DECODING (encodedQuantum[1]); c = DECODING (encodedQuantum[2]); d = DECODING (encodedQuantum[3]); temp = ((UINT4)a) << 18; temp |= ((UINT4)b) << 12; temp |= ((UINT4)c) << 6; temp |=rsaref/test/767key1006440006630000000000000341005153737477011224 037777703401 1 0 Public Key, 767 bits: modulus: 63 71 1d d0 1f 69 e5 b1 5d 61 6c e9 f0 28 3d a2 f0 1c 21 dc 23 f3 1d ca 3c af c2 30 67 1d 0d 8d 74 81 50 7f d3 b6 38 3d e9 68 3b a0 1e fa 0a d2 ed b9 87 b6 1b 29 17 74 27 60 fa 2e 57 da fd 47 1d c5 00 66 86 d7 74 3e ec a4 05 00 9d 50 50 16 90 e7 15 33 be 22 50 15 40 73 6a 5d ed b1 f4 d5 exponent: 01 00 01 Private Key, 767 bits: modulus: 63 71 1d d0 1f 69 e5 b1 5d 61 6c e9 f0 28 3d a2 f0 1c 21 dc 23 f3 1d ca 3c af c2 30 67 1d 0d 8d 74 81 50 7f d3 b6 38 3d e9 68 3b a0 1e fa 0a d2 ed b9 87 b6 1b 29 17 74 27 60 fa 2e 57 da fd 47 1d c5 00 66 86 d7 74 3e ec a4 05 00 9d 50 50 16 90 e7 15 33 be 22 50 15 40 73 6a 5d ed b1 f4 d5 public exponent: 01 00 01 exponent: 32 9d 8a fd 3a 60 1e 87 ee ed fe 0f fd 2b 9e 63 e7 2f 8a 94 90 bf d8 73 ed fb d0 2d ee ee 3c cd b9 75 70 d1 ff a3 0a 71 88 f2 83 16 f7 6d 72 40 4a 9d 0c 80 c1 95 43 42 08 9e f0 42 83 55 6a 7b 47 d8 93 26 5f bc 0e 28 cb 9f 1e 74 0b 86 76 48 3b 8f af e2 4f 97 ff 41 bc 76 a6 d1 29 00 34 69 prime 1: e1 06 cd d0 08 c9 15 09 14 93 8a 8c a5 d7 84 b8 56 15 42 38 b7 e7 8e 89 cb d6 56 9f 59 76 20 10 7f 5e 6e e1 c3 ea 31 41 90 e0 8e 24 47 5e b9 bf prime 2: 71 21 1e d1 49 ff 95 33 e5 60 de 4c ae ae f6 75 11 8b 96 d5 45 45 96 ee 88 a3 3d d9 a1 17 66 42 ae 75 7b c6 18 0a 0d 78 39 b5 5e 99 16 c6 2e 6b prime exponent 1: 32 02 96 19 06 ea d1 8e fc 10 b2 39 01 de 7c f3 8e c6 18 ba 8c 3c 9d 14 08 c6 30 e8 27 34 b6 79 94 25 03 95 8f 39 ec 0a 7b 4d 3c a9 d9 66 b6 f7 prime exponent 2: 4c 4d 14 66 00 4c db ab 16 e8 50 c6 d3 82 ba 43 97 43 d8 c5 9b 65 26 39 57 fb 11 fa 38 c6 79 78 3c 06 8d 26 bc 8b fb 2d bd 6e 70 91 3c 65 0a 65 coefficient: 5b 94 a7 99 4b fc c9 67 a4 4a 88 57 a6 ac 22 63 a0 e4 81 99 f1 ac 62 a8 95 e6 30 60 56 d9 1b 3f 4f 34 0e a1 61 fb 55 28 f0 4e ad 46 a8 f2 7e c4 3401 1 0 rsaref/test/508env.sig1006440006630000000000000014005153737500011756 037777703401 1 0 F0R6K4tWA5A8QjPglg6gHBS9i2GDNJJQuR8DgbHZbt+XlIc0D4ZTrOnKEU3xvUBs+IYH+YbecatqfZwoGMo9DqyMv/8MemWw1006440006630000000000000037005153737473011265 037777703401 1 0 rsaref/test/508env.key1006440006630000000000000013005153737501011764 037777703401 1 0 Aaw5U1IfyJSsIG0juhm9Cdzb/b86rAASB55vARR+AKX50DxmJV+PVM1IY2BsCyI0y/7wsOl612kv+SMyOEyIew==1006440006630000000000000237005153737474011216 037777703401 1 0 rsaref/test/508env.iv1006440006630000000000000001005153737501011607 037777703401 1 0 ˆ£=Ù¡fB73 68 d2 9a 10 e2 6d 36 00 42 83 25 0b b2 71 02 a3 30 46 98 95 26 90 e7 ac 51 02 9f b0 81 6c 2b 1a 1f a4 cc 07 be 7c b5 5b 07 4b 9c d0 88 a0 9b 69 6a c6 9f a6 f9 b4 59 7e 83 82 22 64 1e c1 prime 1: 3f 5e 6e e1 c3 ea 31 41 90 e0 8e 24 47 5e b8 16 f1 21 1e d1 49 ff 95 33 e5 60 de 4c ae ae f7 29 prime 2: 31 06 cd d0 08 c9 15 09 14 93 8a 8c a5 d7 84 b8 56 15 42 38 b7 e7 8e 89 cb d6 56 9f 59 76 20 a5 prime exponent 1: 38 3b e7 0e 36 3b a7 86 55 b8 d0 aa e5 22 eb 1e 80 d1 31 75 ec c3 00 76 d3 41 rsaref/test/508env1006440006630000000000000037005153737502011204 037777703401 1 0 NS5gkx9LkiySo8QZMX56RNLWB7OtrS+QziD2zx5ouzdjgb1dVTOEZg8vcVzBzEL8U0LC7p9rTWgKrNv3l/R7tZwXjB7kSMJ6/krWwEqpalUheHCOxodZVHbq5s1ut5WFOF+WJeKW2SYzJiqjldRKkVVxNKO8njxXDpmMYIdvL3OYBlY31tfg6aiQbl6h6QHgug8n3j6DsqD8gdEEMVibziCf3k4jTa1PE1oGLtlePBW9EFPqaDonyw==37777703401 1 0 rsaref/test/1024key1006440006630000000000000443205153737503011262 037777703401 1 0 Public Key, 1024 bits: modulus: b8 31 41 4e 0b 46 13 92 2b d3 5b 4b 36 80 2b c1 e1 e8 1c 95 a2 7c 95 8f 53 82 00 3d f6 46 15 4c a9 2f c1 ce 02 c3 be 04 7a 45 e9 b0 2a 90 89 b4 b9 02 78 23 7c 96 51 92 a0 fc c8 6b b4 9b c8 2a e6 fd c2 de 70 90 06 b8 6c 76 76 ef df 59 76 26 fa d6 33 a4 f7 dc 48 c4 45 d3 7e b5 5f cb 3b 1a bb 95 ba aa 82 6d 53 90 e1 5f d1 4e d4 03 fa 2d 0c b8 41 c6 50 60 95 24 ec 55 5e 3b c5 6c a9 57 exponent: 01 00 01 Private Key, 1024 bits: modulus: b8 31 41 4e 0b 46 13 92 2b d3 5b 4b 36 80 2b c1 e1 e8 1c 95 a2 7c 95 8f 53 82 00 3d f6 46 15 4c a9 2f c1 ce 02 c3 be 04 7a 45 e9 b0 2a 90 89 b4 b9 02 78 23 7c 96 51 92 a0 fc c8 6b b4 9b c8 2a e6 fd c2 de 70 90 06 b8 6c 76 76 ef df 59 76 26 fa d6 33 a4 f7 dc 48 c4 45 d3 7e b5 5f cb 3b 1a bb 95 ba aa 82 6d 53 90 e1 5f d1 4e d4 03 fa 2d 0c b8 41 c6 50 60 95 24 ec 55 5e 3b c5 6c a9 57 public exponent: 01 00 01 exponent: aa 8f b9 c8 5a 3a 2e ff 49 23 f3 c3 07 19 d2 eb 3b 94 e3 7b 50 b6 8b 0b e8 a9 56 2e 0a 72 45 60 f2 be 2d 79 e6 27 7a 3a cd 3b 16 35 b2 84 9b 6f c5 6e 5a ef 89 7b ec d7 99 c9 da 91 99 f2 33 7c ac 74 cc 10 9e 3a 28 5e a8 cb 70 85 2b a5 65 70 75 26 d5 2f e2 80 b6 2f 3e b4 fb 08 7d 10 dd e7 c5 8b fa 61 ca b1 2b 8f 0d b7 96 34 d9 7c b9 25 08 2b 8d cd 13 95 00 7e 0d bc d9 1f 5c 2d 2e 39 prime 1: e1 06 cd d0 08 c9 15 09 14 93 8a 8c a5 d7 84 b8 56 15 42 38 b7 e7 8e 89 cb d6 56 9f 59 76 20 10 7f 5e 6e e1 c3 ea 31 41 90 e0 8e 24 47 5e b8 16 f1 21 1e d1 49 ff 95 33 e5 60 de 4c ae ae f7 35 prime 2: d1 8b 96 d5 45 45 96 ee 88 a3 3d d9 a1 17 66 42 ae 75 7b c6 18 0a 0d 78 39 b5 5e 99 16 c6 2d d6 ab 02 1b 61 1e a5 0e 9b ee 74 92 c7 10 92 91 70 67 a0 d0 48 6d c8 8c 35 dc 8b 45 ef 4b 55 53 db prime exponent 1: 5c 0f a8 8b ff cc 24 6a fe 9c 0e 06 d4 a2 83 8d d6 ca 03 b9 a8 a3 77 51 30 af 93 e8 c5 74 ea 51 55 8a 90 da 94 88 6f 76 5f 8b 3f 1b e0 87 03 d1 7e fd 09 da 9d e7 8e 67 18 e4 b4 8d b2 b9 aa 31 prime exponent 2: 55 5c 20 b8 86 3c 7f ec 71 9a d6 12 36 6e 3a c9 05 1a 74 ae 50 92 9f c4 0e f6 14 30 16 b7 ea 6a 5d 45 41 74 01 b0 c9 4f ba 06 a0 d8 18 a7 2c 39 f6 ec ea 8b e6 b4 e0 70 fc 83 7b 9c ac 3a 79 2b coefficient: b5 3b 46 e3 6d 17 22 21 96 80 cc df b6 76 4a c7 8f 54 c0 65 5a a4 83 0e c6 34 5e 0b 75 ab 30 fd 6b 26 fc 1b f4 41 2f 5f 48 b9 06 28 55 78 83 dd 5b d4 cb cc 84 f7 6c 81 96 69 87 ae 1b 74 15 23 1 0 rsaref/test/signfile1006440006630000000000000001505153737503011754 037777703401 1 0 Hello world! 67key1006440006630000000000000341005153737477011224 037777703401 1 0 rsaref/test/512env.sig1006440006630000000000000014005153737504011755 037777703401 1 0 0048slGUuWQo0pgaWRi2QOVf5rBXDL+WK4+kpxp5LJFbESruMAUiXqcIyb5Voo6yOZC9yaxJ6YkD1FxQfNl0REG1b9SMCVnqd 50 50 16 90 e7 15 33 be 22 50 15 40 73 6a 5d ed b1 f4 d5 public exponent: 01 00 01 exponent: 32 9d 8a fd 3a 60 1e 87 ee ed fe 0f fd 2b 9e 63 e7 2f 8a 94 90 bf d8 73 ed fb d0 2d ee ee 3c cd b9 75 70 d1 ff a3 0a 71 88 f2 83 16 f7 6d 72 40 4a 9d 0c 80 c1 95 43 42 08 9e f0 42 83 55 6a 7b 47 d8 93 26 5f bc 0e 28 cb 9f 1e 74 0b 86 76 48 3b 8f af e2 4f 97 ff 41 bc 76 a6 d1 29 00 34 69 prime 1: e1 06 cd d0 08 rsaref/test/512env.key1006440006630000000000000013005153737505011763 037777703401 1 0 CL29kjLgt2EyZO2FqncymgY3Di3ym5R7izmWy3MoewnCEs1pw+31Pwd+G05Gg+N+fn2ERA5LCdet+6eX5tw/qQ==91 3c 65 0a 65 coefficient: 5b 94 a7 99 4b fc c9 67 a4 4a 88 57 a6 ac 22 63 a0 e4 81 99 f1 ac 62 a8 95 e6 30 60 56 d9 1b 3f 4f 34 0e a1 61 fb 55 28 f0 4e ad 46 a8 f2 7e c4 3401 1 0 rsaref/test/512env.iv1006440006630000000000000001005153737506011607 037777703401 1 0 “ŠŒ¥×„¸A5A8QjPglg6gHBS9i2GDNJJQuR8DgbHZbt+XlIc0D4ZTrOnKEU3xvUBs+IYH+YbecatqfZwoGMo9DqyMv/8MemWw1006440006630000000000000037005153737473011265 037777703401 1 0 rsaref/test/512env1006440006630000000000000043005153737506011200 037777703401 1 0 CuAWHWVouudDOpNctGDrZnPKuO14soFaUNhWQePc4qggk10nJdEE0CJcTcx4eQ43pMVUuYl9FY3+y0V4PnTan2NjZ90oWQK2966tCmArgsGmDikFccB7Lm9r/ev+oxvpx+Cu/h4yIl0ldtCriTKEbYe4sK7Yp0spW2cbQKVMKOWNRe2zSoW8UgMYat9vdZUdDCYM+tAPX7Pz3F0CFgCcUIFJb/36sXuYROLJef/7OXk+d6y4L6QI8X9F49n0xjv8/4PQvO3H2MwklTUcVRZgXw== 1 0 rsaref/test/512sig1006440006630000000000000013005153737507011170 037777703401 1 0 PdZ7lFx+AVo4bfkpg8aUVTL631akKtAyBBrrwgmDWKL5Qt9oKY9zoOtGha9PhZZuzKp/wlEjVYthKqAc9sp4cg== 9f b0 81 6c 2b 1a 1f a4 cc 07 be 7c b5 5b 07 4b 9c d0 88 a0 9b 69 6a c6 9f a6 f9 b4 59 7e 83 82 22 64 1e c1 prime 1: 3f 5e 6e e1 c3 ea 31 41 90 e0 8e 24 47 5e b8 16 f1 21 1e d1 49 ff 95 33 e5 60 de 4c ae ae f7 29 prime 2: 31 06 cd d0 08 c9 15 09 14 93 8a 8c a5 d7 84 b8 56 15 42 38 b7 e7 8e 89 cb d6 56 9f 59 76 20 a5 prime exponent 1: 38 3b e7 0e 36 3b a7 86 55 b8 d0 aa e5 22 eb 1e 80 d1 31 75 ec c3 00 76 d3 41 rsaref/test/508sig1006440006630000000000000013005153737510011167 037777703401 1 0 AUxA9WhRr+2OQf3rbDPS7CbWdX9lKuE18KXgT91FeRKyj06kFd7w9bDweZyW9pq8Rdtm3J8SFamY4PO0khJy7g==jB7kSMJ6/krWwEqpalUheHCOxodZVHbq5s1ut5WFOF+WJeKW2SYzJiqjldRKkVVxNKO8njxXDpmMYIdvL3OYBlY31tfg6aiQbl6h6QHgug8n3j6DsqD8gdEEMVibziCf3k4jTa1PE1oGLtlePBW9EFPqaDonyw==37777703401 1 0 rsaref/test/767sig1006440006630000000000000020005153737510011174 037777703401 1 0 Q79FGRQtndXwmncCtNZ3Dvr+Xi+MMcHrbWHNOX/Et+Hr3jbuzJ8wlAXLjIZn9CLl8dU1z2tf7pyoW4mg2LzVaLWUnq0BFzQv96P1CEyht+FCcO7LKqsTCnlhaHIs9/19c a9 2f c1 ce 02 c3 be 04 7a 45 e9 b0 2a 90 89 b4 b9 02 78 23 7c 96 51 92 a0 fc c8 6b b4 9b c8 2a e6 fd c2 de 70 90 06 b8 6c 76 76 ef df 59 76 26 fa d6 33 a4 f7 dc 48 c4 45 d3 7e b5 5f cb 3b 1a bb 95 ba aa 82 6d 53 90 e1 5f d1 4e d4 03 fa 2d 0c b8 41 c6 50 60 95 24 ec 55 5e 3b c5 6c a9 57 exponent: 01 00 01 Private Key, 1024 bits: modulus: b8 31 41 4e 0b 46 13 92 2b d3 5b 4brsaref/test/1024sig1006440006630000000000000025405153737511011251 037777703401 1 0 PGZzjpN/5fHKl6/hruiBs6JvTjpufFCxe00xAnCGCFTa36Xg/Eu+0MNrkoLy0kqaSNpdouRh5Y3Q/evVzJcI0MgQTo7BPPCR9Mwhp8/4y83BXxON/NIkK7RZGjjfYhMIw5mXAsIjVdjmufYUVWcVwRNTKVojs7DJcvxKEkGIC8w= fa 61 ca b1 2b 8f 0d b7 96 34 d9 7c b9 25 08 2b 8d cd 13 95 00 7e 0d bc d9 1f 5c 2d 2e 39 prime 1: e1 06 cd d0 08 c9 15 09 14 93 8a 8c a5 d7 84 b8 56 15 42 38 b7 e7 8e 89 cb d6 56 9f 59 76 20 10 7f 5e 6e e1 c3 ea 31 41 90 e0 8e 24 47 5e b8 16 f1 21 1e d1 49 ff 95 33 e5 60 de 4c ae ae f7 35 prime 2: d1 8b 96 d5 45 45 96 ee 88 a3 3d rsaref/test/md2test.in1006440006630000000000000003405153737512012144 037777703401 1 0 v n signfile 512sig.md2 1 q ec ea 8b e6 b4 e0 70 fc 83 7b 9c ac 3a 79 2b coefficient: b5 3b 46 e3 6d 17 22 21 96 80 cc df b6 76 4a c7 8f 54 c0 65 5a a4 83 0e c6 34 5e 0b 75 ab 30 fd 6b 26 fc 1b f4 41 2f 5f 48 b9 06 28 55 78 83 dd 5b d4 cb cc 84 f7 6c 81 96 69 87 ae 1b 74 15 23 1 0 0048slGUuWQo0pgaWRi2QOVf5rBXDL+WK4+kpxp5LJFbESruMAUiXqcIyb5Voo6yOZC9yaxJ6YkD1FxQfNl0REG1b9SMCVnqd 50 50 16 90 e7 15 33 be 22 50 15 40 73 6a 5d ed b1 f4 d5 public exponent: 01 00 01 exponent: 32 9d 8a fd 3a 60 1e 87 ee ed fe 0f fd 2b 9e 63 e7 2f 8a 94 90 bf d8 73 ed fb d0 2d ee ee 3c cd b9 75 70 d1 ff a3 0a 71 88 f2 83 16 f7 6d 72 40 4a 9d 0c 80 c1 95 43 42 08 9e f0 42 83 55 6a 7b 47 d8 93 26 5f bc 0e 28 cb 9f 1e 74 0b 86 76 48 3b 8f af e2 4f 97 ff 41 bc 76 a6 d1 29 00 34 69 prime 1: e1 06 cd d0 08 rsaref/test/512env.key1006440006630000000000000013005153737505011763 037777703401 1 0 CL29kjLgt2EyZO2FqncymgY3Di3ym5R7izmWy3MoewnCEs1pw+31Pwd+G05Gg+N+fn2ERA5LCdet+6eX5tw/qQ==91 3c 65 0a 65 coefficient: 5b 94 a7 99 4b fc c9 67 a4 4a 88 57 a6 ac 22 63 a0 e4 81 99 f1 ac 62 a8 95 e6 30 60 56 d9 1b 3f 4f 34 0e a1 61 fb 55 28 f0 4e ad 46 a8 f2 7e c4 3401 1 0 rsaref/test/512env.iv1006440006630000000000000001005153737506011607 037777703401 1 0 “ŠŒ¥×„¸A5A8QjPglg6gHBS9i2GDNJJQuR8DgbHZbt+XlIc0D4ZTrOnKEU3xvUBs+IYH+YbecatqfZwoGMo9DqyMv/8MemWw1006440006630000000000000037005153737473011265 037777703401 1 0 rsaref/test/512env1006440006630000000000000043005153737506011200 037777703401 1 0 CuAWHWVouudDOpNctGDrZnPKuO14soFaUNhWQePc4qggk10nJdEE0CJcTcx4eQ43pMVUuYl9FY3+y0V4PnTan2NjZ90oWQK2966tCmArgsGmDikFccB7Lm9r/ev+oxvpx+Cu/h4yIl0ldtCriTKEbYe4sK7Yp0spW2cbQKVMKOWNRe2zSoW8UgMYat9vdZUdDCYM+tAPX7Pz3F0CFgCcUIFJb/36sXuYROLJef/7OXk+d6y4L6QI8X9F49n0xjv8/4PQvO3H2MwklTUcVRZgXw== 1 0 rsaref/test/512sig1006440006630000000000000013005153737507011170 037777703401 1 0