Annotation of pgp/src/rsaglue1.c, revision 1.1.1.2

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.