📄 r_enhanc.c
字号:
/* R_ENHANC.C - cryptographic enhancements for RSAREF *//* Copyright (C) RSA Laboratories, a division of RSA Data Security, Inc., created 1991. All rights reserved. */#include "global.h"#include "rsaref.h"#include "r_random.h"#include "rsa.h"/* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5), then DIGEST_INFO_B, then 16-byte message digest. */static unsigned char DIGEST_INFO_A[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02};#define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A)static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };#define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B)#define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16)static unsigned char *PADDING[] = { (unsigned char *)"", (unsigned char *)"\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_LENstatic void R_EncodeDigestInfo PROTO_LIST ((unsigned char *, int, unsigned char *));static void EncryptPEMUpdateFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *, unsigned int));static int DecryptPEMUpdateFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *, unsigned int));static int CipherInit PROTO_LIST ((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int));static void CipherUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int));static void CipherRestart PROTO_LIST ((R_ENVELOPE_CTX *));int R_DigestInit (context, digestAlgorithm)R_DIGEST_CTX *context; /* new context */int digestAlgorithm; /* message-digest algorithm */{ context->digestAlgorithm = digestAlgorithm; switch (digestAlgorithm) { case DA_MD2: MD2Init (&context->context.md2); break; case DA_MD5: MD5Init (&context->context.md5); break; default: return (RE_DIGEST_ALGORITHM); } return (0);}int R_DigestUpdate (context, partIn, partInLen)R_DIGEST_CTX *context; /* context */unsigned char *partIn; /* next data part */unsigned int partInLen; /* length of next data part */{ if (context->digestAlgorithm == DA_MD2) MD2Update (&context->context.md2, partIn, partInLen); else MD5Update (&context->context.md5, partIn, partInLen); return (0);}int R_DigestFinal (context, digest, digestLen)R_DIGEST_CTX *context; /* context */unsigned char *digest; /* message digest */unsigned int *digestLen; /* length of message digest */{ *digestLen = 16; if (context->digestAlgorithm == DA_MD2) MD2Final (digest, &context->context.md2); else MD5Final (digest, &context->context.md5); return (0);}int R_SignInit (context, digestAlgorithm)R_SIGNATURE_CTX *context; /* new context */int digestAlgorithm; /* message-digest algorithm */{ return (R_DigestInit (&context->digestContext, digestAlgorithm));}int R_SignUpdate (context, partIn, partInLen)R_SIGNATURE_CTX *context; /* context */unsigned char *partIn; /* next data part */unsigned int partInLen; /* length of next data part */{ return (R_DigestUpdate (&context->digestContext, partIn, partInLen));}int R_SignFinal (context, signature, signatureLen, privateKey)R_SIGNATURE_CTX *context; /* context */unsigned char *signature; /* signature */unsigned int *signatureLen; /* length of signature */R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */{ int status; unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN]; unsigned int digestLen; do { if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen)) != 0) break; R_EncodeDigestInfo (digestInfo, context->digestContext.digestAlgorithm, digest); if (RSAPrivateEncrypt (signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey) != 0) { status = RE_PRIVATE_KEY; break; } /* Reset for another verification. Assume Init won't fail */ R_DigestInit (&context->digestContext, context->digestContext.digestAlgorithm); } while (0); /* Zeroize potentially sensitive information. */ R_memset ((POINTER)digest, 0, sizeof (digest)); R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo)); return (status);}int R_VerifyInit (context, digestAlgorithm)R_SIGNATURE_CTX *context; /* new context */int digestAlgorithm; /* message-digest algorithm */{ return (R_DigestInit (&context->digestContext, digestAlgorithm));}int R_VerifyUpdate (context, partIn, partInLen)R_SIGNATURE_CTX *context; /* context */unsigned char *partIn; /* next data part */unsigned int partInLen; /* length of next data part */{ return (R_DigestUpdate (&context->digestContext, partIn, partInLen));}int R_VerifyFinal (context, signature, signatureLen, publicKey)R_SIGNATURE_CTX *context; /* context */unsigned char *signature; /* signature */unsigned int signatureLen; /* length of signature */R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */{ int status; unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN], originalDigestInfo[MAX_SIGNATURE_LEN]; unsigned int originalDigestInfoLen, digestLen; if (signatureLen > MAX_SIGNATURE_LEN) return (RE_LEN); status = 0; do { if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen)) != 0) break; R_EncodeDigestInfo (digestInfo, context->digestContext.digestAlgorithm, digest); if (RSAPublicDecrypt (originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, publicKey) != 0) { status = RE_PUBLIC_KEY; break; } if ((originalDigestInfoLen != DIGEST_INFO_LEN) || (R_memcmp ((POINTER)originalDigestInfo, (POINTER)digestInfo, DIGEST_INFO_LEN))) { status = RE_SIGNATURE; break; } /* Reset for another verification. Assume Init won't fail */ R_DigestInit (&context->digestContext, context->digestContext.digestAlgorithm); } 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);}/* Caller must ASCII recode the encrypted keys if desired. */int R_SealInit (context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys, encryptionAlgorithm, randomStruct)R_ENVELOPE_CTX *context; /* new context */unsigned char **encryptedKeys; /* encrypted keys */unsigned int *encryptedKeyLens; /* lengths of encrypted keys */unsigned char iv[8]; /* initialization vector */unsigned int publicKeyCount; /* number of public keys */R_RSA_PUBLIC_KEY **publicKeys; /* public keys */int encryptionAlgorithm; /* data encryption algorithm */R_RANDOM_STRUCT *randomStruct; /* random structure */{ int status; unsigned char key[24]; unsigned int keyLen, i; do { context->encryptionAlgorithm = encryptionAlgorithm; keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24; if ((status = R_GenerateBytes (key, keyLen, randomStruct)) != 0) break; if ((status = R_GenerateBytes (iv, 8, randomStruct)) != 0) break; if (encryptionAlgorithm == EA_DES_EDE2_CBC) /* Make both E keys the same */ R_memcpy ((POINTER)(key + 16), (POINTER)key, 8); if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) != 0) break; for (i = 0; i < publicKeyCount; ++i) { if (RSAPublicEncrypt (encryptedKeys[i], &encryptedKeyLens[i], key, keyLen, publicKeys[i], randomStruct)) { status = RE_PUBLIC_KEY; break; } } if (status != 0) break; context->bufferLen = 0; } while (0); /* Zeroize sensitive information. */ R_memset ((POINTER)key, 0, sizeof (key)); return (status);}/* Assume partOut buffer is at least partInLen + 7, since this may flush buffered input. */int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen)R_ENVELOPE_CTX *context; /* context */unsigned char *partOut; /* next encrypted data part */unsigned int *partOutLen; /* length of next encrypted data part */unsigned char *partIn; /* next data part */unsigned int partInLen; /* length of next data part */{ unsigned int tempLen; tempLen = 8 - context->bufferLen; if (partInLen < tempLen) { /* Just accumulate into buffer. */ R_memcpy ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, partInLen); context->bufferLen += partInLen; *partOutLen = 0; return (0); } /* Fill the buffer and encrypt. */ R_memcpy ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, tempLen); CipherUpdate (context, partOut, context->buffer, 8); partIn += tempLen; partInLen -= tempLen; partOut += 8; *partOutLen = 8; /* Encrypt as many 8-byte blocks as possible. */ tempLen = 8 * (partInLen / 8); CipherUpdate (context, partOut, partIn, tempLen); partIn += tempLen; partInLen -= tempLen; *partOutLen += tempLen; /* Length is now less than 8, so copy remainder to buffer. */ R_memcpy ((POINTER)context->buffer, (POINTER)partIn,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -