Line data Source code
1 : /**
2 : * @file telegram_server_key.c [TEST_ONLY]
3 : * @brief Test-only RSA key pair for functional DH handshake tests.
4 : *
5 : * WARNING: TEST_ONLY — NEVER use these keys in production.
6 : *
7 : * This 2048-bit RSA key pair was generated solely for testing purposes.
8 : * The public key is embedded here so the production fingerprint check
9 : * passes; the private key is embedded in mock_tel_server.c so the mock
10 : * server can decrypt the client's RSA_PAD-encrypted inner_data and
11 : * complete the full DH handshake with real OpenSSL on both sides.
12 : *
13 : * Key fingerprint computation:
14 : * SHA1(n_LE_4bytes_len + n_bytes + e_LE_4bytes_len + e_bytes)
15 : * lower 64 bits (little-endian) = 0x8671de275f1cabc5
16 : *
17 : * Linked by: functional-test-runner
18 : * NOT linked by: tg-cli, tg-cli-ro, tg-tui, or any unit test runner.
19 : *
20 : * FEAT-38: also implements telegram_server_key_get_pem(),
21 : * telegram_server_key_get_fingerprint(), and telegram_server_key_set_override()
22 : * so the mock shadows the entire production translation unit.
23 : */
24 :
25 : #include "telegram_server_key.h"
26 :
27 : #include <stdint.h>
28 : #include <stdlib.h>
29 : #include <string.h>
30 :
31 : /* TEST_ONLY: 2048-bit RSA public key fingerprint (file-local). */
32 : static const uint64_t TELEGRAM_RSA_FINGERPRINT = 0x8671de275f1cabc5ULL;
33 :
34 : /* TEST_ONLY: 2048-bit RSA public key (PKCS#8 SubjectPublicKeyInfo format). */
35 : static const char * const TELEGRAM_RSA_PEM =
36 : "-----BEGIN PUBLIC KEY-----\n"
37 : "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmxv4/EXb0wAFr/O9GshQ\n"
38 : "mySO93xBAeN/5fzZ6HGHgIfS/2XL/R8GMBTl5rPaNnHL6fnv+BhOeb1M2PF6zNYe\n"
39 : "nbQpRmDb0Tab3LYX5la6RhiIyh9m97J4qeGo7VDnGSMk8p2aNbzBubqgsWGl1soQ\n"
40 : "cDDyUPOxsOVm3GijSVoN42dRiNIPrSVAKl6Xz8BdyoysyGcGv625yfYnJDl9djmh\n"
41 : "tXNnp1tfrL9Stas+gnMZmwskbg/sVClUyx3OcpJnGAyddgixEvA3X2zzrVBgD9PN\n"
42 : "gkDqbX6T5uX751OnOd7LiCLZ3XY4k++PockAV0Kb1lyiGcxRHYMSdkFM6U5UcKlY\n"
43 : "owIDAQAB\n"
44 : "-----END PUBLIC KEY-----\n";
45 :
46 : /* ---- FEAT-38 runtime override (test stub) ---- */
47 :
48 : static char *g_mock_override_pem = NULL;
49 : static uint64_t g_mock_override_fingerprint = 0;
50 :
51 8 : const char *telegram_server_key_get_pem(void) {
52 8 : return g_mock_override_pem ? g_mock_override_pem : TELEGRAM_RSA_PEM;
53 : }
54 :
55 17 : uint64_t telegram_server_key_get_fingerprint(void) {
56 : return g_mock_override_pem
57 17 : ? g_mock_override_fingerprint
58 17 : : TELEGRAM_RSA_FINGERPRINT;
59 : }
60 :
61 : /**
62 : * Expand literal \\n → '\n' in @p src; return heap-allocated result.
63 : * (Duplicated from production telegram_server_key.c — kept private.)
64 : */
65 1 : static char *mock_expand_newlines(const char *src) {
66 1 : size_t src_len = strlen(src);
67 1 : char *dst = malloc(src_len + 1);
68 1 : if (!dst) return NULL;
69 1 : size_t di = 0;
70 127 : for (size_t si = 0; si < src_len; si++) {
71 126 : if (src[si] == '\\' && si + 1 < src_len && src[si + 1] == 'n') {
72 4 : dst[di++] = '\n';
73 4 : si++;
74 : } else {
75 122 : dst[di++] = src[si];
76 : }
77 : }
78 1 : dst[di] = '\0';
79 1 : return dst;
80 : }
81 :
82 7 : int telegram_server_key_set_override(const char *pem) {
83 : /* In functional tests we accept any non-NULL PEM and store it.
84 : * Fingerprint computation is skipped (we hard-code the test key's
85 : * known fingerprint for the override path, or just reuse the mock's). */
86 7 : if (!pem) {
87 6 : free(g_mock_override_pem);
88 6 : g_mock_override_pem = NULL;
89 6 : g_mock_override_fingerprint = 0;
90 6 : return 0;
91 : }
92 1 : char *expanded = mock_expand_newlines(pem);
93 1 : if (!expanded) return -1;
94 1 : free(g_mock_override_pem);
95 1 : g_mock_override_pem = expanded;
96 : /* Reuse the mock fingerprint so the handshake still works when the
97 : * caller sets the mock PEM verbatim. */
98 1 : g_mock_override_fingerprint = TELEGRAM_RSA_FINGERPRINT;
99 1 : return 0;
100 : }
|