crypto_drv.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 702 行 · 第 1/2 页
C
702 行
/* buf = <<rlen:32/integer,topmask:8/integer,bottommask:8/integer>> */ if (len != 6) return -1; rlen = get_int32(buf); *rbuf = (char *)(bin = driver_alloc_binary(rlen)); RAND_pseudo_bytes(bin->orig_bytes,rlen); or_mask = ((unsigned char*)buf)[4]; bin->orig_bytes[rlen-1] |= or_mask; /* topmask */ or_mask = ((unsigned char*)buf)[5]; bin->orig_bytes[0] |= or_mask; /* bottommask */ return rlen; break; case DRV_RAND_UNIFORM: /* buf = <<from_len:32/integer,bn_from:from_len/binary, * * to_len:32/integer,bn_to:to_len/binary>> */ if (len < 8) return -1; from_len = get_int32(buf); if (len < (8 + from_len)) return -1; to_len = get_int32(buf + 4 + from_len); if (len != (8 + from_len + to_len)) return -1; bn_from = BN_new(); BN_bin2bn((unsigned char *)(buf + 4), from_len, bn_from); bn_rand = BN_new(); BN_bin2bn((unsigned char *)(buf + 8 + from_len), to_len, bn_rand); bn_to = BN_new(); BN_sub(bn_to, bn_rand, bn_from); BN_pseudo_rand_range(bn_rand, bn_to); BN_add(bn_rand, bn_rand, bn_from); rlen = BN_num_bytes(bn_rand); *rbuf = (char *)(bin = driver_alloc_binary(rlen + 4)); put_int32(bin->orig_bytes, rlen); BN_bn2bin(bn_rand,(unsigned char*)(bin->orig_bytes + 4)); BN_free(bn_rand); BN_free(bn_from); BN_free(bn_to); return rlen + 4; break; case DRV_MOD_EXP: /* buf = <<base_len:32/integer,base/binary, * * exponent_len:32/integer,exponent/binary, * * modulo_len:32/integer, modulo/binary>> */ if (len < 12) return -1; base_len = get_int32(buf); if (len < (12 + base_len)) return -1; exponent_len = get_int32(buf + 4 + base_len); if (len < (12 + base_len + exponent_len)) return -1; modulo_len = get_int32(buf + 8 + base_len + exponent_len); if (len != (12 + base_len + exponent_len + modulo_len)) return -1; bn_base = BN_new(); BN_bin2bn((unsigned char *)(buf + 4), base_len, bn_base); bn_exponent = BN_new(); BN_bin2bn((unsigned char *)(buf + 8 + base_len), exponent_len, bn_exponent); bn_modulo = BN_new(); BN_bin2bn((unsigned char *)(buf + 12 + base_len + exponent_len), modulo_len, bn_modulo); bn_result = BN_new(); bn_ctx = BN_CTX_new(); BN_mod_exp(bn_result, bn_base, bn_exponent, bn_modulo, bn_ctx); rlen = BN_num_bytes(bn_result); *rbuf = (char *)(bin = driver_alloc_binary(rlen + 4)); put_int32(bin->orig_bytes, rlen); BN_bn2bin(bn_result,(unsigned char*)(bin->orig_bytes + 4)); BN_free(bn_result); BN_free(bn_modulo); BN_free(bn_exponent); BN_free(bn_base); BN_CTX_free(bn_ctx); return rlen + 4; break; case DRV_DSS_VERIFY: /* buf = <<data_len:32/integer,data:data_len/binary, * dsa_r:20/binary, * dsa_s:20/binary, * dsa_p_len:32/integer, dsa_p:dsa_p_len/binary, * dsa_q_len:32/integer, dsa_q:dsa_q_len/binary, * dsa_g_len:32/integer, dsa_r:dsa_r_len/binary, * dsa_y_len:32/integer, dsa_y:dsa_y_len/binary>> */ i = 0; j = 0; if (len < 60) return -1; data_len = get_int32(buf + i + j); j += data_len; i += 44; if (len < (60 + j)) return -1; dsa_p_len = get_int32(buf + i + j); j += dsa_p_len; i += 4; if (len < (60 + j)) return -1; dsa_q_len = get_int32(buf + i + j); j += dsa_q_len; i += 4; if (len < (60 + j)) return -1; dsa_g_len = get_int32(buf + i + j); j += dsa_g_len; i += 4; if (len < (60 + j)) return -1; dsa_y_len = get_int32(buf + i + j); j += dsa_y_len; if (len < (60 + j)) return -1; i = 4; SHA1((unsigned char *) (buf + i), data_len, hmacbuf); dsa_sig = DSA_SIG_new(); dsa_r = BN_new(); i += data_len; BN_bin2bn((unsigned char *)(buf + i), 20, dsa_r); i += 20; dsa_s = BN_new(); BN_bin2bn((unsigned char *)(buf + i), 20, dsa_s); i += 24; dsa_sig->r = dsa_r; dsa_sig->s = dsa_s; dsa_p = BN_new(); BN_bin2bn((unsigned char *)(buf + i), dsa_p_len, dsa_p); i += (dsa_p_len + 4); dsa_q = BN_new(); BN_bin2bn((unsigned char *)(buf + i), dsa_q_len, dsa_q); i += (dsa_q_len + 4); dsa_g = BN_new(); BN_bin2bn((unsigned char *)(buf + i), dsa_g_len, dsa_g); i += (dsa_g_len + 4); dsa_y = BN_new(); BN_bin2bn((unsigned char *)(buf + i), dsa_y_len, dsa_y); dsa = DSA_new(); dsa->p = dsa_p; dsa->q = dsa_q; dsa->g = dsa_g; dsa->priv_key = NULL; dsa->pub_key = dsa_y; i = DSA_do_verify(hmacbuf, SHA_DIGEST_LENGTH, dsa_sig, dsa); *rbuf = (char *)(bin = driver_alloc_binary(1)); (bin->orig_bytes)[0] = (char)(i & 0xff); DSA_free(dsa); DSA_SIG_free(dsa_sig); /* Apparently, the DSA_do_verify operation allocates some space * which must be freed this way: */ CRYPTO_cleanup_all_ex_data(); return 1; break; case DRV_RSA_VERIFY: /* buf = <<data_len:32/integer, data:data_len/binary, * rsa_s_len:32/integer, rsa_s:rsa_s_len/binary, * rsa_e_len:32/integer, rsa_e:rsa_e_len/binary, * rsa_n_len:32/integer, rsa_n:rsa_n_len/binary>> */ i = 0; j = 0; if (len < 16) return -1; data_len = get_int32(buf + i + j); j += data_len; i += 4; if (len < (16 + j)) return -1; rsa_s_len = get_int32(buf + i + j); j += rsa_s_len; i += 4; if (len < (16 + j)) return -1; rsa_e_len = get_int32(buf + i + j); j += rsa_e_len; i += 4; if (len < (16 + j)) return -1; rsa_n_len = get_int32(buf + i + j); j += rsa_n_len; i += 4; if (len < (16 + j)) return -1; i = 4; SHA1((unsigned char *) (buf + i), data_len, hmacbuf); i += (data_len + 4); rsa_s = (unsigned char *)(buf + i); i += (rsa_s_len + 4); rsa_e = BN_new(); BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e); i += (rsa_e_len + 4); rsa_n = BN_new(); BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n); rsa = RSA_new(); rsa->n = rsa_n; rsa->e = rsa_e; i = RSA_verify(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH, rsa_s, rsa_s_len, rsa); *rbuf = (char *)(bin = driver_alloc_binary(1)); (bin->orig_bytes)[0] = (char)(i & 0xff); RSA_free(rsa); /* Apparently, the RSA_verify operation allocates some space * which must be freed this way, but perhaps it would suffice to * do it in stop()? */ CRYPTO_cleanup_all_ex_data(); return 1; break; case DRV_CBC_AES128_ENCRYPT: /* buf = <<key:16/binary, ivec:16/binary, data/binary>> */ dlen = len - 32; if (dlen < 0) return -1; /* There is no AES_KEY_new, probably meant to be used through EVP_xxx, so: */ *rbuf = (char *)(bin = driver_alloc_binary(dlen)); AES_set_encrypt_key((unsigned char *) buf, 128, &aes_key); AES_cbc_encrypt((unsigned char *) (buf + 32), (unsigned char *) bin->orig_bytes, dlen, &aes_key, (unsigned char *) (buf + 16), AES_ENCRYPT); return dlen; break; case DRV_CBC_AES128_DECRYPT: /* buf = key[16] ivec[16] data */ dlen = len - 32; if (dlen < 0) return -1; /* There is no AES_KEY_new, probably meant to be used through EVP_xxx, so: */ *rbuf = (char *)(bin = driver_alloc_binary(dlen)); AES_set_decrypt_key((unsigned char *) buf, 128, &aes_key); AES_cbc_encrypt((unsigned char *) (buf + 32), (unsigned char *) bin->orig_bytes, dlen, &aes_key, (unsigned char *) (buf + 16), AES_DECRYPT); return dlen; break; case DRV_XOR: /* buf = data1, data2 with same size */ dlen = len / 2; if (len != dlen * 2) return -1; *rbuf = p = (char *)(bin = driver_alloc_binary(dlen)); dbuf = buf + dlen; for (key = buf, key2 = dbuf; key != dbuf; ++key, ++key2, ++p) *p = *key ^ *key2; return dlen; break; default: break; } return -1;}/* HMAC */static void hmac_md5(char *key, int klen, char *dbuf, int dlen, char *hmacbuf){ MD5_CTX ctx; char ipad[HMAC_INT_LEN]; char opad[HMAC_INT_LEN]; char nkey[MD5_LEN]; int i; /* Change key if longer than 64 bytes */ if (klen > HMAC_INT_LEN) { MD5_CTX kctx; MD5_Init(&kctx); MD5_Update(&kctx, key, klen); MD5_Final(nkey, &kctx); key = nkey; klen = MD5_LEN; } memset(ipad, '\0', sizeof(ipad)); memset(opad, '\0', sizeof(opad)); memcpy(ipad, key, klen); memcpy(opad, key, klen); for (i = 0; i < HMAC_INT_LEN; i++) { ipad[i] ^= HMAC_IPAD; opad[i] ^= HMAC_OPAD; } /* inner MD5 */ MD5_Init(&ctx); MD5_Update(&ctx, ipad, HMAC_INT_LEN); MD5_Update(&ctx, dbuf, dlen); MD5_Final(hmacbuf, &ctx); /* outer MD5 */ MD5_Init(&ctx); MD5_Update(&ctx, opad, HMAC_INT_LEN); MD5_Update(&ctx, hmacbuf, MD5_LEN); MD5_Final(hmacbuf, &ctx);}static void hmac_sha1(char *key, int klen, char *dbuf, int dlen, char *hmacbuf){ SHA_CTX ctx; char ipad[HMAC_INT_LEN]; char opad[HMAC_INT_LEN]; char nkey[SHA_LEN]; int i; /* Change key if longer than 64 bytes */ if (klen > HMAC_INT_LEN) { SHA_CTX kctx; SHA1_Init(&kctx); SHA1_Update(&kctx, key, klen); SHA1_Final(nkey, &kctx); key = nkey; klen = SHA_LEN; } memset(ipad, '\0', sizeof(ipad)); memset(opad, '\0', sizeof(opad)); memcpy(ipad, key, klen); memcpy(opad, key, klen); for (i = 0; i < HMAC_INT_LEN; i++) { ipad[i] ^= HMAC_IPAD; opad[i] ^= HMAC_OPAD; } /* inner SHA */ SHA1_Init(&ctx); SHA1_Update(&ctx, ipad, HMAC_INT_LEN); SHA1_Update(&ctx, dbuf, dlen); SHA1_Final(hmacbuf, &ctx); /* outer SHA */ SHA1_Init(&ctx); SHA1_Update(&ctx, opad, HMAC_INT_LEN); SHA1_Update(&ctx, hmacbuf, SHA_LEN); SHA1_Final(hmacbuf, &ctx);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?