|
|
1.1.1.2 ! root 1: /* ! 2: * rsaglue1.c - These functions wrap and unwrap message digests (MDs) and ! 3: * data encryption keys (DEKs) in padding and RSA-encrypt them into ! 4: * multi-precision integers. This layer of abstraction was introduced ! 5: * to allow the transparent use of either the RSAREF Cryptographic ! 6: * Toolkit from RSA Data Security Inc for the RSA calculations (where ! 7: * the RSA patent applies), or, Philip Zimmermann's mpi library for the ! 8: * RSA calculations. The rsaglue.c module from PGP version 2.3a performs ! 9: * the same functions as this module, but can be compiled to select the ! 10: * use of mpilib functions instead of RSAREF as the underlying math engine. ! 11: * That version of rsaglue.c would be suitable where the RSA patent does ! 12: * not apply, such as Canada. ! 13: * ! 14: * This file uses MPILIB to perform the actual encryption and decryption. ! 15: * It uses the same PKCS format as RSAREF, although it also accepts an older ! 16: * format used in PGP 2.1. ! 17: * ! 18: * (c) Copyright 1990-1996 by Philip Zimmermann. All rights reserved. ! 19: * The author assumes no liability for damages resulting from the use ! 20: * of this software, even if the damage results from defects in this ! 21: * software. No warranty is expressed or implied. ! 22: * ! 23: * Note that while most PGP source modules bear Philip Zimmermann's ! 24: * copyright notice, many of them have been revised or entirely written ! 25: * by contributors who frequently failed to put their names in their ! 26: * code. Code that has been incorporated into PGP from other authors ! 27: * was either originally published in the public domain or is used with ! 28: * permission from the various authors. ! 29: * ! 30: * PGP is available for free to the public under certain restrictions. ! 31: * See the PGP User's Guide (included in the release package) for ! 32: * important information about licensing, patent restrictions on ! 33: * certain algorithms, trademarks, copyrights, and export controls. ! 34: */ ! 35: ! 36: #include <string.h> /* for mem*() */ ! 37: #include "mpilib.h" ! 38: #include "mpiio.h" ! 39: #include "pgp.h" ! 40: #include "rsaglue.h" ! 41: #include "random.h" /* for cryptRandByte() */ ! 42: ! 43: /* No RSADSI credit for MPI version */ ! 44: char signon_legalese[] = ""; ! 45: ! 46: /* These functions hide all the internal details of RSA-encrypted ! 47: * keys and digests. They owe a lot of their heritage to ! 48: * the preblock() and postunblock() routines in mpiio.c. ! 49: */ ! 50: ! 51: /* Abstract Syntax Notation One (ASN.1) Distinguished Encoding Rules (DER) ! 52: encoding for RSA/MD5, used in PKCS-format signatures. */ ! 53: static byte asn_array[] = { /* PKCS 01 block type 01 data */ ! 54: 0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, ! 55: 0x02,0x05,0x05,0x00,0x04,0x10 }; ! 56: /* This many bytes from the end, there's a zero byte */ ! 57: #define ASN_ZERO_END 3 ! 58: ! 59: int ! 60: rsa_public_encrypt(unitptr outbuf, byteptr inbuf, short bytes, ! 61: unitptr E, unitptr N) ! 62: /* Encrypt a DEK with a public key. Returns 0 on success. ! 63: * <0 means there was an error. ! 64: * -1: Generic error ! 65: * -3: Key too big ! 66: * -4: Key too small ! 67: */ ! 68: { ! 69: unit temp[MAX_UNIT_PRECISION]; ! 70: unsigned int blocksize; ! 71: int i; /* Temporary, and holds error codes */ ! 72: byte *p = (byte *)temp; ! 73: ! 74: /* ! 75: * We are building the mpi in place, except for a possible ! 76: * byte-order swap to little-endian at the end. Thus, we ! 77: * need to fill the buffer with leading 0's in the unused ! 78: * most significant byte positions. ! 79: */ ! 80: blocksize = countbytes(N) - 1; /* Bytes available for user data */ ! 81: for (i = units2bytes(global_precision) - blocksize; i > 0; --i) ! 82: *p++ = 0; ! 83: /* ! 84: * Both the PKCS and PGP 2.0 key formats add a type byte, and a ! 85: * a framing byte of 0 to the user data. The remaining space ! 86: * is filled with random padding. (PKCS requires that there be ! 87: * at least 1 byte of padding.) ! 88: */ ! 89: i = blocksize - 2 - bytes; ! 90: ! 91: if (i < 1) /* Less than minimum padding? */ ! 92: return -4; ! 93: *p++ = CK_ENCRYPTED_BYTE; /* Type byte */ ! 94: while (i) /* Non-zero random padding */ ! 95: if ((*p = cryptRandByte())) ! 96: ++p, --i; ! 97: *p++ = 0; /* Framing byte */ ! 98: memcpy(p, inbuf, bytes); /* User data */ ! 99: ! 100: mp_convert_order((byte *)temp); /* Convert buffer to MPI */ ! 101: i = mp_modexp(outbuf, temp, E, N); /* Do the encryption */ ! 102: if (i < 0) ! 103: i = -1; ! 104: ! 105: Cleanup: ! 106: mp_burn(temp); ! 107: return i < 0 ? i : 0; ! 108: } /* rsa_public_encrypt */ ! 109: ! 110: int ! 111: rsa_private_encrypt(unitptr outbuf, byteptr inbuf, short bytes, ! 112: unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N) ! 113: /* Encrypt a message digest with a private key. ! 114: * Returns <0 on error: ! 115: * -1: generic error ! 116: * -4: Key too big ! 117: * -5: Key too small ! 118: */ ! 119: { ! 120: unit temp[MAX_UNIT_PRECISION]; ! 121: unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION]; ! 122: byte *p; ! 123: int i; ! 124: unsigned int blocksize; ! 125: ! 126: /* PGP doesn't store these coefficents, so we need to compute them. */ ! 127: mp_move(temp,P); ! 128: mp_dec(temp); ! 129: mp_mod(DP,D,temp); ! 130: mp_move(temp,Q); ! 131: mp_dec(temp); ! 132: mp_mod(DQ,D,temp); ! 133: ! 134: p = (byte *)temp; ! 135: ! 136: ! 137: /* We are building the mpi in place, except for a possible ! 138: * byte-order swap to little-endian at the end. Thus, we ! 139: * need to fill the buffer with leading 0's in the unused ! 140: * most significant byte positions. ! 141: */ ! 142: blocksize = countbytes(N) - 1; /* Space available for data */ ! 143: for (i = units2bytes(global_precision) - blocksize; i > 0; --i) ! 144: *p++ = 0; ! 145: ! 146: i = blocksize - 2 - bytes; /* Padding needed */ ! 147: i -= sizeof(asn_array); /* Space for type encoding */ ! 148: if (i < 0) { ! 149: i = -4; /* Error code */ ! 150: goto Cleanup; ! 151: } ! 152: *p++ = MD_ENCRYPTED_BYTE; /* Type byte */ ! 153: memset(p, ~0, i); /* All 1's padding */ ! 154: p += i; ! 155: *p++ = 0; /* Zero framing byte */ ! 156: memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */ ! 157: p += sizeof(asn_array); ! 158: memcpy(p, inbuf, bytes); /* User data */ ! 159: ! 160: mp_convert_order((byte *)temp); ! 161: i = mp_modexp_crt(outbuf, temp, P, Q, DP, DQ, U); /* Encrypt */ ! 162: if (i < 0) ! 163: i = -1; ! 164: ! 165: Cleanup: ! 166: burn(temp); ! 167: ! 168: return i; ! 169: } /* rsa_private_encrypt */ ! 170: ! 171: /* Remove a signature packet from an MPI */ ! 172: /* Thus, we expect constant padding and the MIC ASN sequence */ ! 173: int ! 174: rsa_public_decrypt(byteptr outbuf, unitptr inbuf, ! 175: unitptr E, unitptr N) ! 176: /* Decrypt a message digest using a public key. Returns the number of bytes ! 177: * extracted, or <0 on error. ! 178: * -1: Corrupted packet. ! 179: * -3: Key too big ! 180: * -4: Key too small ! 181: * -5: Maybe malformed RSA packet ! 182: * -7: Unknown conventional algorithm ! 183: * -9: Malformed RSA packet ! 184: */ ! 185: { ! 186: unit temp[MAX_UNIT_PRECISION]; ! 187: unsigned int blocksize; ! 188: int i; ! 189: byte *front, *back; ! 190: ! 191: i = mp_modexp(temp, inbuf, E, N); ! 192: if (i < 0) { ! 193: mp_burn(temp); ! 194: return -1; ! 195: } ! 196: mp_convert_order((byte *)temp); ! 197: blocksize = countbytes(N) - 1; ! 198: front = (byte *)temp; /* Points to start of block */ ! 199: i = units2bytes(global_precision); ! 200: back = front + i; /* Points to end of block */ ! 201: i -= countbytes(N) - 1; /* Expected leading 0's */ ! 202: ! 203: /* ! 204: * Strip off the padding. This handles both PKCS and PGP 2.0 ! 205: * formats. If we're using RSAREF2, we use the padding-removal ! 206: * code in RSAPublicDecrypt, which accepts only PKCS style. ! 207: * Oh, well. ! 208: */ ! 209: ! 210: if (i < 0) /* This shouldn't happen */ ! 211: goto ErrorReturn; ! 212: while (i--) /* Extra bytes should be 0 */ ! 213: if (*front++) ! 214: goto ErrorReturn; ! 215: ! 216: /* How to distinguish old PGP from PKCS formats. ! 217: * The old PGP format ends in a trailing type byte, with ! 218: * all 1's padding before that. The PKCS format ends in ! 219: * 16 bytes of message digest, preceded by an ASN string ! 220: * which is not all 1's. ! 221: */ ! 222: if (back[-1] == MD_ENCRYPTED_BYTE && ! 223: back[-17] == 0xff && back[-18] == 0xff) { ! 224: /* Old PGP format: Padding is at the end */ ! 225: if (*--back != MD_ENCRYPTED_BYTE) ! 226: goto ErrorReturn; ! 227: if (*front++ != MD5_ALGORITHM_BYTE) { ! 228: mp_burn(temp); ! 229: return -7; ! 230: } ! 231: while (*--back == 0xff) /* Skip constant padding */ ! 232: ; ! 233: if (*back) /* It should end with a zero */ ! 234: goto ErrorReturn; ! 235: } else { ! 236: /* PKCS format: padding at the beginning */ ! 237: if (*front++ != MD_ENCRYPTED_BYTE) ! 238: goto ErrorReturn; ! 239: while (*front++ == 0xff) /* Skip constant padding */ ! 240: ; ! 241: if (front[-1]) /* First non-FF byte should be 0 */ ! 242: goto ErrorReturn; ! 243: /* Then comes the ASN header */ ! 244: if (memcmp(front, asn_array, sizeof(asn_array))) { ! 245: mp_burn(temp); ! 246: return -7; ! 247: } ! 248: front += sizeof(asn_array); ! 249: } ! 250: ! 251: /* We're done - copy user data to outbuf */ ! 252: if (back < front) ! 253: goto ErrorReturn; ! 254: blocksize = back-front; ! 255: memcpy(outbuf, front, blocksize); ! 256: mp_burn(temp); ! 257: return blocksize; ! 258: ErrorReturn: ! 259: mp_burn(temp); ! 260: return -9; ! 261: } /* rsa_public_decrypt */ ! 262: ! 263: /* We expect to find random padding and an encryption key */ ! 264: int ! 265: rsa_private_decrypt(byteptr outbuf, unitptr inbuf, ! 266: unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N) ! 267: /* Decrypt an encryption key using a private key. Returns the number of bytes ! 268: * extracted, or <0 on error. ! 269: * -1: Generic error ! 270: * -3: Key too big ! 271: * -4: Key too small ! 272: * -5: Maybe malformed RSA ! 273: * -7: Unknown conventional algorithm ! 274: * -9: Malformed RSA packet ! 275: */ ! 276: { ! 277: byte *back; ! 278: byte *front; ! 279: unsigned int blocksize; ! 280: unit temp[MAX_UNIT_PRECISION]; ! 281: unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION]; ! 282: int i; ! 283: ! 284: /* PGP doesn't store (d mod p-1) and (d mod q-1), so compute 'em */ ! 285: mp_move(temp,P); ! 286: mp_dec(temp); ! 287: mp_mod(DP,D,temp); ! 288: mp_move(temp,Q); ! 289: mp_dec(temp); ! 290: mp_mod(DQ,D,temp); ! 291: ! 292: i = mp_modexp_crt(temp, inbuf, P, Q, DP, DQ, U); ! 293: mp_burn(DP); ! 294: mp_burn(DQ); ! 295: if (i < 0) { ! 296: mp_burn(temp); ! 297: return -1; ! 298: } ! 299: mp_convert_order((byte *)temp); ! 300: front = (byte *)temp; /* Start of block */ ! 301: i = units2bytes(global_precision); ! 302: back = (byte *)front + i; /* End of block */ ! 303: blocksize = countbytes(N) - 1; ! 304: i -= blocksize; /* Expected # of leading 0's */ ! 305: ! 306: if (i < 0) /* This shouldn't happen */ ! 307: goto Corrupted; ! 308: while (i--) /* Extra bytes should be 0 */ ! 309: if (*front++) ! 310: goto Corrupted; ! 311: ! 312: /* How to distinguish old PGP from PKCS formats. ! 313: * PGP packets have a trailing type byte (CK_ENCRYPTED_BYTE), ! 314: * while PKCS formats have it leading. ! 315: */ ! 316: if (front[0] != CK_ENCRYPTED_BYTE && back[-1] == CK_ENCRYPTED_BYTE) { ! 317: /* PGP 2.0 format - padding at the end */ ! 318: if (back[-1] != CK_ENCRYPTED_BYTE) ! 319: goto Corrupted; ! 320: while (*--back) /* Skip non-zero random padding */ ! 321: ; ! 322: } else { ! 323: /* PKCS format - padding at the beginning */ ! 324: if (*front++ != CK_ENCRYPTED_BYTE) ! 325: goto Corrupted; ! 326: while (*front++) /* Skip non-zero random padding */ ! 327: ; ! 328: } ! 329: if (back <= front) ! 330: goto Corrupted; ! 331: blocksize = back-front; ! 332: ! 333: memcpy(outbuf, front, blocksize); ! 334: mp_burn(temp); ! 335: return blocksize; ! 336: ! 337: Corrupted: ! 338: mp_burn(temp); ! 339: return -9; ! 340: } /* rsa_private_decrypt */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.