📄 rsa_nss.c
字号:
crypt_key* key = g_malloc(sizeof(crypt_key)); /* For Private keys: */ const CK_MECHANISM_TYPE SymEncryptionType = CKM_DES3_CBC_PAD; PK11SlotInfo *symSlot; PK11SymKey *symKey; SECItem *pubKeyValue; SECItem symKeyItem; /* storage space for binary key import */ unsigned char symKeyData[24] = {0}; SECItem *iv = 0, *wrappedKey = 0, label; CK_ATTRIBUTE_TYPE attribs[3] = { CKA_SIGN, CKA_DECRYPT, CKA_SIGN_RECOVER }; const int NumAttribs = 3; int cur_piece; CERTSubjectPublicKeyInfo *certPubKeyInfo; /* key_str looks like "KKKKK" or "KKKKK,NNNN,MMMM", where */ /* KKKKK is the Base64 encoding of the public key, or */ /* NNNN is the Base64 encoding of the IV, and */ /* MMMM is the Base64 encoding of the encrypted private key */ key->proto = rsa_nss_proto; split_key = g_strsplit(key_str, ",", 3); key->store.rsa_nss.pub = 0; key->store.rsa_nss.priv = 0; cur_piece = 0; // Check for public key part, and get it: if (split_key[cur_piece] == 0) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 1, _("Error parsing RSANSS key\n")); g_free(key); g_strfreev(split_key); return 0; } wrappedKey = NSSBase64_DecodeBuffer(0, 0, split_key[cur_piece], strlen(split_key[cur_piece])); if (wrappedKey == 0) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 2, _("Error parsing RSANSS key\n")); g_free(key); g_strfreev(split_key); return 0; } certPubKeyInfo = SECKEY_DecodeDERSubjectPublicKeyInfo(wrappedKey); PORT_Free(wrappedKey->data); PORT_Free(wrappedKey); if (certPubKeyInfo == NULL) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 3, _("Error parsing RSANSS key\n")); g_free(key); g_strfreev(split_key); return 0; } key->store.rsa_nss.pub = SECKEY_ExtractPublicKey(certPubKeyInfo); if (key->store.rsa_nss.pub == NULL) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 4, _("Error parsing RSANSS key\n")); g_free(key); g_strfreev(split_key); return 0; } SECKEY_DestroySubjectPublicKeyInfo(certPubKeyInfo); generate_digest(key->digest, key->store.rsa_nss.pub); generate_fingerprint(key->fingerprint, key->store.rsa_nss.pub); g_snprintf(key->length, sizeof(key->length), "%d", 8 * SECKEY_PublicKeyStrength(key->store.rsa_nss.pub)); if (split_key[++cur_piece] == 0) { /* No private part, so return a public key: */ g_strfreev(split_key); return key; } /* ------------------------------------------------------------------------ */ /* Extract Private key: */ /* */ iv = NSSBase64_DecodeBuffer(0, 0, split_key[cur_piece], strlen(split_key[cur_piece])); if (split_key[++cur_piece] == 0) { /* only part of a private key */ gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 5, _("Error parsing RSANSS key\n")); g_free(key); g_strfreev(split_key); return 0; } wrappedKey = NSSBase64_DecodeBuffer(0, 0, split_key[cur_piece], strlen(split_key[cur_piece])); if ((iv == 0) || (wrappedKey == 0)) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 6, _("Error parsing RSANSS key\n")); g_free(key); g_strfreev(split_key); return 0; } pubKeyValue = SECITEM_DupItem(&key->store.rsa_nss.pub->u.rsa.modulus); symSlot = PK11_GetBestSlot(SymEncryptionType, NULL); g_assert(symSlot != 0); symKeyItem.data = &symKeyData[0]; symKeyItem.len = sizeof(symKeyData); symKey = PK11_ImportSymKey(symSlot, PK11_GetKeyGen(SymEncryptionType), PK11_OriginUnwrap, CKA_WRAP, &symKeyItem, NULL); if (!symKey) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 7, _("Error parsing RSANSS key\n")); g_strfreev(split_key); SECKEY_DestroyPublicKey(key->store.rsa_nss.pub); SECITEM_FreeItem (pubKeyValue, PR_TRUE); g_free(key); return 0; } label.data = NULL; label.len = 0; key->store.rsa_nss.priv = PK11_UnwrapPrivKey(symSlot, symKey, SymEncryptionType, iv, wrappedKey, &label, pubKeyValue, PR_FALSE, PR_FALSE, CKK_RSA, attribs, NumAttribs, 0); SECITEM_FreeItem (pubKeyValue, PR_TRUE); if (key->store.rsa_nss.priv == 0) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "(%d) %s", 8, _("Error parsing RSANSS key\n")); g_strfreev(split_key); SECKEY_DestroyPublicKey(key->store.rsa_nss.pub); g_free(key); return 0; } /* should sanity check public/private pair */ g_strfreev(split_key); return key;} crypt_key* rsa_nss_make_pub_from_priv(crypt_key* priv_key) { crypt_key* pub_key = g_malloc(sizeof(crypt_key)); pub_key->proto = rsa_nss_proto; strcpy(pub_key->length, priv_key->length); strncpy(pub_key->digest, priv_key->digest, KEY_DIGEST_LENGTH); strncpy(pub_key->fingerprint, priv_key->fingerprint, KEY_FINGERPRINT_LENGTH); pub_key->store.rsa_nss.pub = copy_public_rsa_key(priv_key->store.rsa_nss.pub); pub_key->store.rsa_nss.priv = 0; return pub_key;}int rsa_nss_encrypt(unsigned char** encrypted, unsigned char* msg, int msg_len, crypt_key* pub_key){ SECKEYPublicKey * key = pub_key->store.rsa_nss.pub; int modulus_len = SECKEY_PublicKeyStrength(key); int unpadded_block_len = oaep_max_unpadded_len(modulus_len); int num_blocks = ((msg_len - 1) / unpadded_block_len) + 1; unsigned char* msg_cur, *encrypt_cur; int msg_block_len; unsigned char *padded_block = g_malloc(modulus_len); int ret; SECStatus rv; // gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Starting Encrypt\n"); *encrypted = g_malloc(num_blocks * modulus_len); msg_cur = msg; encrypt_cur = *encrypted; while (msg_cur < msg + msg_len) { msg_block_len = unpadded_block_len; if (msg_cur + msg_block_len > msg + msg_len) { msg_block_len = msg + msg_len - msg_cur; } ret = oaep_pad_block(padded_block, modulus_len, msg_cur, msg_block_len); if (!ret) { g_free(padded_block); g_free(*encrypted); *encrypted = 0; return 0; } rv = PK11_PubEncryptRaw(key, encrypt_cur, padded_block, modulus_len, 0); if (rv != SECSuccess) { g_free(padded_block); g_free(*encrypted); *encrypted = 0; return 0; } msg_cur += msg_block_len; encrypt_cur += modulus_len; } g_free(padded_block); // gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Ending Encrypt\n"); return (encrypt_cur - *encrypted);}int rsa_nss_decrypt(unsigned char** decrypted, unsigned char* msg, int msg_len, crypt_key* priv_key){ SECKEYPrivateKey * key = priv_key->store.rsa_nss.priv; int modulus_len = SECKEY_PublicKeyStrength(priv_key->store.rsa_nss.pub); int unpadded_block_len = oaep_max_unpadded_len(modulus_len); int num_blocks = msg_len / modulus_len; unsigned char* msg_cur, *decrypt_cur; int decrypt_block_size; unsigned char *padded_block = g_malloc(modulus_len); int ret; SECStatus rv; gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Starting Decrypt\n"); *decrypted = g_malloc(num_blocks * unpadded_block_len + 1); msg_cur = msg; decrypt_cur = *decrypted; if (num_blocks * modulus_len != msg_len) { /* not an even number of blocks */ gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "Not a multiple of block len: %d %d %d\n", num_blocks, modulus_len, msg_len); g_free(padded_block); g_free(*decrypted); *decrypted = 0; return 0; } while (msg_cur < msg + msg_len) { rv = PK11_PubDecryptRaw(key, padded_block, &decrypt_block_size, modulus_len, msg_cur, modulus_len); if (rv != SECSuccess) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "PubDecryptRaw failed %d\n", rv); g_free(padded_block); g_free(*decrypted); *decrypted = 0; return 0; } g_assert(decrypt_block_size == modulus_len); /* for now. Don't understand how */ /* this could not be true */ ret = oaep_unpad_block(decrypt_cur, &decrypt_block_size, padded_block, modulus_len); if (!ret) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "OAEP unpadding failed\n"); return 0; } msg_cur += modulus_len; decrypt_cur += decrypt_block_size; } /* Null terminate what just came out, in case someone tries to use it as a string */ *decrypt_cur = 0; // gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Ending Decrypt\n"); return (decrypt_cur - *decrypted);}int rsa_nss_sign(unsigned char** signed_msg, unsigned char* msg, int msg_len, crypt_key* priv_key, crypt_key* pub_key) { SECKEYPrivateKey * key = priv_key->store.rsa_nss.priv; int modulus_len = SECKEY_PublicKeyStrength(priv_key->store.rsa_nss.pub); unsigned char *sig_pos, *tmp_sig; SECStatus rv; int out_block_size; const int salt_len = 20; gchar *nonce_str = GE_nonce_to_str(&pub_key->store.rsa_nss.nonce); int nonce_len = strlen(nonce_str); GE_incr_nonce(&pub_key->store.rsa_nss.nonce); *signed_msg = g_malloc(msg_len + modulus_len + nonce_len + 1); tmp_sig = g_malloc(modulus_len); memcpy(*signed_msg, nonce_str, nonce_len); (*signed_msg)[nonce_len]=':'; memcpy(*signed_msg + nonce_len + 1, msg, msg_len); sig_pos = *signed_msg + msg_len + nonce_len + 1 ; pss_generate_sig(tmp_sig, modulus_len, *signed_msg, msg_len + nonce_len + 1, salt_len); rv = PK11_PubDecryptRaw(key, sig_pos, &out_block_size, modulus_len, tmp_sig, modulus_len); if (rv != SECSuccess) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "PK11_PubDecryptRaw Failed\n"); g_free(*signed_msg); *signed_msg = 0; return 0; } g_assert(out_block_size == modulus_len); /* dunno why they yield out_block_size */ g_free(tmp_sig); return msg_len + nonce_len + 1 + modulus_len;}// Returns length of authed string, or 0 if not authenticated// g_malloc's space for the authed string, and null terminates the result// If returning zero, may return a message ID (nonce) as the authed stringint rsa_nss_auth(unsigned char** authed, unsigned char* msg, int msg_len, crypt_key* pub_key, const char* name) { SECKEYPublicKey * key = pub_key->store.rsa_nss.pub; int modulus_len = SECKEY_PublicKeyStrength(key); unsigned char *tmp_sig; SECStatus rv; int verified; gchar *nonce_msg, **nonce_msg_split; gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Starting Auth\n"); *authed = 0; if (msg_len < modulus_len) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "Bad msg_len in Auth\n"); return -1; } tmp_sig = g_malloc(modulus_len); rv = PK11_PubEncryptRaw(key, tmp_sig, msg + msg_len - modulus_len, modulus_len, 0); if (rv != SECSuccess) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "PK11_PubEncryptRaw Failed\n"); g_free(tmp_sig); return -1; } /* gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Auth 2\n"); */ verified = pss_check_sig(tmp_sig, modulus_len, msg, msg_len - modulus_len); g_free(tmp_sig); if (!verified) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", _("Bad signature on message (len %d, mod %d)\n"), msg_len, modulus_len); return -1; } /* gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Auth 3\n"); */ nonce_msg = g_strndup(msg, msg_len - modulus_len); nonce_msg_split = g_strsplit(nonce_msg, ":", 2); g_free(nonce_msg); /* gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Auth 4\n"); */ if ((nonce_msg_split[0] == 0) || (nonce_msg_split[1] == 0)) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "No Nonce in message\n"); g_strfreev(nonce_msg_split); return -1; } /* gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Auth 5\n"); */ if (!GE_check_incoming_nonce(name, nonce_msg_split[0])) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "Bad Nonce in message\n"); *authed = g_strdup(nonce_msg_split[0]); g_strfreev(nonce_msg_split); return -1; } /* gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Auth 6\n"); */ *authed = nonce_msg_split[1]; g_free(nonce_msg_split[0]); g_free(nonce_msg_split); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Auth End\n"); return strlen(*authed);}int rsa_nss_calc_unencrypted_size(struct crypt_key* key, int insize) { int modulus_len = SECKEY_PublicKeyStrength(key->store.rsa_nss.pub); int unpadded_block_len = oaep_max_unpadded_len(modulus_len); int num_blocks = insize / modulus_len; /* floor: max number of blocks that could fit */ return num_blocks * unpadded_block_len;}int rsa_nss_calc_unsigned_size(struct crypt_key* key, int insize) { int modulus_len, nonce_len; gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "calc_unsigned_size\n"); modulus_len = SECKEY_PublicKeyStrength(key->store.rsa_nss.pub); nonce_len = GE_nonce_str_len(); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "modulus_len:%d:%d\n", modulus_len, nonce_len); if (insize < modulus_len + nonce_len) return 0; return insize - modulus_len - nonce_len - 1; /* -1 from ":" after nonce */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -