Error compiling .c program files using Visual C++ 2022

Need help compiling Encryption C program files downloaded from Github please:
https://github.com/tbuktu/libntru

Downloaded zip file has src folder with about 30 .c and .h files.
I have renamed .c files to .cpp files.
File bench.cpp has main() function.

Created Visual C++ 2022 console project and added these .cpp and .h files to the project.

File hash.cpp is giving compile error:

Error (active) E0065 expected a ';' hash.cpp 15

Need help in compiling bench.cpp and other needed c++ files from src folder of the zip file please.

Because of many files and each file has many lines of code, not posting these src files to this forum.

If possible for others to compile these files and help me by letting me know the steps for fixing compile errors, I sincerely appreciate and very thankful for your help please.

Thanks and best regards,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//  hash.cpp
#include <string.h>
#include <stdint.h>
#include "sph_sha1.h"
#include "sph_sha2.h"
#include "hash.h"
#include "hash_simd.h"

#ifdef NTRU_DETECT_SIMD
uint32_t OPENSSL_ia32cap_P[] __attribute__((visibility("hidden"))) = {0, 0, 0, 0};
#else
#ifdef __AVX2__
/* don’t detect SHA extensions for now, just report AVX/AVX2 */
uint32_t OPENSSL_ia32cap_P[] __attribute__((visibility("hidden"))) = {0, 1<<28, 1<<5, 0};
#else
uint32_t OPENSSL_ia32cap_P[] __attribute__((visibility("hidden"))) = {0, 0, 0, 0};
#endif
#endif   /* NTRU_DETECT_SIMD */
Last edited on
Need help compiling Encryption C program


So why not compile as c programs? why re-name .c files to .cpp files? VS will compile .c files as c programs.

Also note that __attribute__ is not supported in VS. It's a GCC extension.

Re symbol visibility (or not), this may help
https://stackoverflow.com/questions/12717991/symbol-visibility-in-windows

PS If you look at the github page, it says libntru is supported on Windows via MingW - not VS.
Last edited on
Hi Seeplus,

Thank you very much for great help and excellent inputs.

Please give me some detailed steps for compiling this code as a c program.

I do not know how to how to compile using MingW.



VS will compile .c files as c programs.


Thanks and best regards,



https://en.wikipedia.org/wiki/NTRUEncrypt

https://tbuktu.github.io/ntru/
Last edited on
I don't use GCC or MingW so can't help with that. As a starter, I'd first try removing __attribute__((visibility("hidden"))) and see what happens...

Please give me some detailed steps for compiling this code as a c program.


You just use VS as normal with files with .c extension rather than .cpp. VS automatically compiles a .c file as c code and .cpp file as c++ code. You don't do anything special. You can even mix .c and .cpp files in the same project.
Last edited on
Thank you, thank you and thank you, seeplus.
I will follow the steps you have suggested, by using .c files in VS2022.

Best regards,

if you want to use it as-is, I really like the cygwin (unix tools on windows including g++, python, more) toolset. It can compile MOST unixified c++ natively for use on windows.

With any luck, there is a makefile that will just work. Bad luck, the makefile may not work without tampering, and really bad luck, not provided at all.

If you do have a makefile, visual studio can usually craft a project from it, but that won't help with unix specific files/g++ specific commands, you will still have to fix all that.

Sometimes there is no choice (sigh), but as I got older I reached a point where if downloaded code does not build within about half an hour, it goes in the garbage bin. If just getting it to work requires days of fighting with it, its going to be so special purpose that its the only code online for that job, ok... you either rewrite it or fight the compiler. That is a rare situation, unless you are doing extremely specialized things, usually R&D.
Thank you jonnin, I will follow all of your guidance and compile as c program in VS2022.

Best regards,
To compile at a time small portions of bench.c file's main function, I am using

1
2
#if 0
#endif  


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 // bench.c
int main(int argc, char **argv) {
    printf("Please wait...\n");

    uint8_t success = 1;

#if 0

    NtruEncParams param_arr[] = ALL_PARAM_SETS;


    uint8_t param_idx;
    for (param_idx=0; param_idx<sizeof(param_arr)/sizeof(param_arr[0]); param_idx++) {
        NtruEncParams params = param_arr[param_idx];
        NtruEncKeyPair kp;
        uint32_t i;
        struct timespec t1, t2;
        printf("%-10s   ", params.name);
        fflush(stdout);

        double samples_keygen[NUM_ITER_KEYGEN];
        NtruRandGen rng = NTRU_RNG_DEFAULT;
        NtruRandContext rand_ctx;
        success &= ntru_rand_init(&rand_ctx, &rng) == NTRU_SUCCESS;
        for (i=0; i<NUM_ITER_KEYGEN; i++) {
            clock_gettime(CLOCK_REALTIME, &t1);
            success &= ntru_gen_key_pair(&params, &kp, &rand_ctx) == NTRU_SUCCESS;
            clock_gettime(CLOCK_REALTIME, &t2);
            double duration = 1000000000.0*(t2.tv_sec-t1.tv_sec) + t2.tv_nsec-t1.tv_nsec;   /* nanoseconds */
            samples_keygen[i] = duration / 1000.0;   /* microseconds */
        }
        print_time("keygen", samples_keygen, NUM_ITER_KEYGEN);

        double samples_encdec[NUM_ITER_ENCDEC];
        uint16_t max_len = ntru_max_msg_len(&params);   /* max message length for this param set */
        uint8_t plain[max_len];
        success &= ntru_rand_generate(plain, max_len, &rand_ctx) == NTRU_SUCCESS;
        uint16_t enc_len = ntru_enc_len(&params);
        uint8_t encrypted[enc_len];
        uint8_t decrypted[max_len];
        for (i=0; i<NUM_ITER_ENCDEC; i++) {
            clock_gettime(CLOCK_REALTIME, &t1);
            success &= ntru_encrypt((uint8_t*)&plain, max_len, &kp.pub, &params, &rand_ctx, (uint8_t*)&encrypted) == NTRU_SUCCESS;
            clock_gettime(CLOCK_REALTIME, &t2);
            double duration = 1000000000.0*(t2.tv_sec-t1.tv_sec) + t2.tv_nsec-t1.tv_nsec;   /* nanoseconds */
            samples_encdec[i] = duration / 1000.0;   /* microseconds */
        }
        print_time("enc", samples_encdec, NUM_ITER_ENCDEC);
        success &= ntru_rand_release(&rand_ctx) == NTRU_SUCCESS;

        uint16_t dec_len;
        for (i=0; i<NUM_ITER_ENCDEC; i++) {
            clock_gettime(CLOCK_REALTIME, &t1);
            success &= ntru_decrypt((uint8_t*)&encrypted, &kp, &params, (uint8_t*)&decrypted, &dec_len) == NTRU_SUCCESS;
            clock_gettime(CLOCK_REALTIME, &t2);
            double duration = 1000000000.0*(t2.tv_sec-t1.tv_sec) + t2.tv_nsec-t1.tv_nsec;   /* nanoseconds */
            samples_encdec[i] = duration / 1000.0;   /* microseconds */
        }
        print_time("dec", samples_encdec, NUM_ITER_ENCDEC);
        printf("\n");
    }

#endif


    if (!success)
        printf("Error!\n");
    return success ? 0 : 1;
}
Last edited on
Above is giving following error:

Error C2057 expected constant expression idxgen.c 29 inp_len



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// idxgen.c

#include <stdlib.h>
#include <string.h>
#include "idxgen.h"
#include "ntru_endian.h"

void ntru_IGF_init(uint8_t *seed, uint16_t seed_len, const NtruEncParams *params, NtruIGFState *s) {
    s->Z = seed;
    s->zlen = seed_len;
    s->N = params->N;
    s->c = params->c;
    s->rnd_thresh = (1<<s->c) - (1<<s->c)%s->N;
    s->hlen = params->hlen;
    s->rem_len = params->min_calls_r * 8 * s->hlen;
    s->hash = params->hash;
    s->hash_4way = params->hash_4way;
    s->hash_8way = params->hash_8way;
    s->counter = 0;

    s->buf.num_bytes = 0;
    s->buf.last_byte_bits = 0;

    while (s->counter < params->min_calls_r-7) {
        uint8_t H_arr[8][NTRU_MAX_HASH_LEN];
        uint16_t inp_len = s->zlen + sizeof s->counter;

        uint8_t j;
        uint8_t hash_inp_arr[8][inp_len];
        uint8_t *hash_inp[8];
        for (j=0; j<8; j++) {
            memcpy(&hash_inp_arr[j], (uint8_t*)s->Z, s->zlen);
            uint16_t counter_endian = htole16(s->counter);
            memcpy((uint8_t*)&hash_inp_arr[j] + s->zlen, &counter_endian, sizeof s->counter);
            hash_inp[j] = hash_inp_arr[j];
            s->counter++;
        }
        uint8_t *H[8];
        for (j=0; j<8; j++)
            H[j] = H_arr[j];
        s->hash_8way(hash_inp, inp_len, H);
        for (j=0; j<8; j++)
            ntru_append(&s->buf, H[j], s->hlen);
    }
    while (s->counter < params->min_calls_r-3) {
        uint8_t H_arr[4][NTRU_MAX_HASH_LEN];
        uint16_t inp_len = s->zlen + sizeof s->counter;

        uint8_t j;
        uint8_t hash_inp_arr[4][inp_len];
        uint8_t *hash_inp[4];
        for (j=0; j<4; j++) {
            memcpy(&hash_inp_arr[j], (uint8_t*)s->Z, s->zlen);
            uint16_t counter_endian = htole16(s->counter);
            memcpy((uint8_t*)&hash_inp_arr[j] + s->zlen, &counter_endian, sizeof s->counter);
            hash_inp[j] = hash_inp_arr[j];
            s->counter++;
        }
        uint8_t *H[4];
        for (j=0; j<4; j++)
            H[j] = H_arr[j];
        s->hash_4way(hash_inp, inp_len, H);
        for (j=0; j<4; j++)
            ntru_append(&s->buf, H[j], s->hlen);
    }
    while (s->counter < params->min_calls_r) {
        uint8_t H[NTRU_MAX_HASH_LEN];
        uint16_t inp_len = s->zlen + sizeof s->counter;
        uint8_t hash_inp[inp_len];
        memcpy(&hash_inp, (uint8_t*)s->Z, s->zlen);
        uint16_t counter_endian = htole16(s->counter);
        memcpy((uint8_t*)&hash_inp + s->zlen, &counter_endian, sizeof s->counter);
        s->hash((uint8_t*)&hash_inp, inp_len, (uint8_t*)&H);

        ntru_append(&s->buf, (uint8_t*)&H, s->hlen);
        s->counter++;
    }
}

void ntru_IGF_next(NtruIGFState *s, uint16_t *i) {
    uint16_t N = s-> N;
    uint16_t c = s-> c;

    uint8_t H[NTRU_MAX_HASH_LEN];

    for (;;) {
        if (s->rem_len < c) {
            NtruBitStr M;
            ntru_trailing(&s->buf, s->rem_len, &M);
            uint16_t tmp_len = c - s->rem_len;
            uint16_t c_thresh = s->counter + (tmp_len+s->hlen-1) / s->hlen;
            while (s->counter < c_thresh) {
                uint16_t inp_len = s->zlen + sizeof s->counter;
                uint8_t hash_inp[inp_len];
                memcpy(&hash_inp, (uint8_t*)s->Z, s->zlen);
                uint16_t counter_endian = htole16(s->counter);
                memcpy((uint8_t*)&hash_inp + s->zlen, &counter_endian, sizeof s->counter);
                s->hash((uint8_t*)&hash_inp, inp_len, (uint8_t*)&H);

                ntru_append(&M, (uint8_t*)&H, s->hlen);
                s->counter++;
                s->rem_len += 8 * s->hlen;
            }
            s->buf = M;
        }

        *i = ntru_leading(&s->buf, c);   /* assume c<32 */
        ntru_truncate(&s->buf, c);
        s->rem_len -= c;
        if (*i < s->rnd_thresh) {   /* if (*i < (1<<c)-(1<<c)%N) */
            while (*i >= N)
                *i -= N;
            return;
        }
    }
}
Last edited on
I have added const on line 26 (i.e. line 5 in the below code fragment) and showed below the lines 24, through 30.

Still the error exists on line 8 (i.e. line 29) below:

Error C2057 expected constant expression idxgen.c 29
Error C2466 cannot allocate an array of constant size 0 idxgen.c 29
Error C2087 'hash_inp_arr': missing subscript idxgen.c 29


How to fix this error please?

1
2
3
4
5
6
7
8
9
    
// idxgen.c
    while (s->counter < params->min_calls_r-7) {
        uint8_t H_arr[8][NTRU_MAX_HASH_LEN];
        const uint16_t inp_len = s->zlen + sizeof s->counter;

        uint8_t j;
        uint8_t hash_inp_arr[8][inp_len];
        uint8_t *hash_inp[8];
Last edited on
A regular C style array requires the dimensions to be known at compile time, apparently line 26 is instantiating inp_len with run-time values. *BUZZ!*
You are probably going to need to use manual memory management for your run-time sized arrays. *ICK!*

If this were C++ code you could use a 2-dimension std::vector and let the C++ run-time deal with all that.

The easiest (somewhat) way to do this is have a simulated 2D array set up as a 1D array.
In C (as opposed to C++) the array size DOESN’T need to be known at compile time.
lastchance wrote:
In C (as opposed to C++) the array size DOESN’T need to be known at compile time.

This feature is called variable-length array (VLA) and was introduced in C99. It was made optional in C11 which means that conforming compilers don't have to support it.

Microsoft's compiler does not support this feature as far as I know.
Removed all .c and .h files files except bench.c from VS 2022 project and compiled without errors and got following results:

Please wait...


Below given minimal bench.c is working:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// bench.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// #include "ntru.h"
#include <stdint.h>

#define NUM_ITER_KEYGEN 50
#define NUM_ITER_ENCDEC 10000

int compare_double(const void *p1, const void *p2) {
    double t1 = *(double*)p1;
    double t2 = *(double*)p2;
    return t1<t2 ? -1 : (t1>t2 ? 1 : 0);
}

double median(double *samples, int num_samples) {
    if (num_samples == 0)
        return 0;
    if (num_samples == 1)
        return samples[0];
    qsort(samples, num_samples, sizeof(samples[0]), compare_double);
    if (num_samples%2 == 0)
        return (samples[num_samples/2-1]+samples[num_samples/2]) / 2;
    else
        return samples[num_samples/2];
}

void print_time(char *label, double *samples, int num_samples) {
    double time = median(samples, num_samples);
    double per_sec = 1000000.0 / time;

//     printf("%s %dus=%d/sec   ", label, (uint32_t)time, (uint32_t)per_sec);
    printf("%s %ldus=%ld/sec   ", label, (long)time, (long)per_sec);

    fflush(stdout);
}

int main(int argc, char **argv) {
    printf("Please wait...\n");

    uint8_t success = 1;

#if 0

    NtruEncParams param_arr[] = ALL_PARAM_SETS;


    uint8_t param_idx;
    for (param_idx=0; param_idx<sizeof(param_arr)/sizeof(param_arr[0]); param_idx++) {
        NtruEncParams params = param_arr[param_idx];
        NtruEncKeyPair kp;
        uint32_t i;
        struct timespec t1, t2;
        printf("%-10s   ", params.name);
        fflush(stdout);

        double samples_keygen[NUM_ITER_KEYGEN];
        NtruRandGen rng = NTRU_RNG_DEFAULT;
        NtruRandContext rand_ctx;
        success &= ntru_rand_init(&rand_ctx, &rng) == NTRU_SUCCESS;
        for (i=0; i<NUM_ITER_KEYGEN; i++) {
            clock_gettime(CLOCK_REALTIME, &t1);
            success &= ntru_gen_key_pair(&params, &kp, &rand_ctx) == NTRU_SUCCESS;
            clock_gettime(CLOCK_REALTIME, &t2);
            double duration = 1000000000.0*(t2.tv_sec-t1.tv_sec) + t2.tv_nsec-t1.tv_nsec;   /* nanoseconds */
            samples_keygen[i] = duration / 1000.0;   /* microseconds */
        }
        print_time("keygen", samples_keygen, NUM_ITER_KEYGEN);

        double samples_encdec[NUM_ITER_ENCDEC];
        uint16_t max_len = ntru_max_msg_len(&params);   /* max message length for this param set */
        uint8_t plain[max_len];
        success &= ntru_rand_generate(plain, max_len, &rand_ctx) == NTRU_SUCCESS;
        uint16_t enc_len = ntru_enc_len(&params);
        uint8_t encrypted[enc_len];
        uint8_t decrypted[max_len];
        for (i=0; i<NUM_ITER_ENCDEC; i++) {
            clock_gettime(CLOCK_REALTIME, &t1);
            success &= ntru_encrypt((uint8_t*)&plain, max_len, &kp.pub, &params, &rand_ctx, (uint8_t*)&encrypted) == NTRU_SUCCESS;
            clock_gettime(CLOCK_REALTIME, &t2);
            double duration = 1000000000.0*(t2.tv_sec-t1.tv_sec) + t2.tv_nsec-t1.tv_nsec;   /* nanoseconds */
            samples_encdec[i] = duration / 1000.0;   /* microseconds */
        }
        print_time("enc", samples_encdec, NUM_ITER_ENCDEC);
        success &= ntru_rand_release(&rand_ctx) == NTRU_SUCCESS;

        uint16_t dec_len;
        for (i=0; i<NUM_ITER_ENCDEC; i++) {
            clock_gettime(CLOCK_REALTIME, &t1);
            success &= ntru_decrypt((uint8_t*)&encrypted, &kp, &params, (uint8_t*)&decrypted, &dec_len) == NTRU_SUCCESS;
            clock_gettime(CLOCK_REALTIME, &t2);
            double duration = 1000000000.0*(t2.tv_sec-t1.tv_sec) + t2.tv_nsec-t1.tv_nsec;   /* nanoseconds */
            samples_encdec[i] = duration / 1000.0;   /* microseconds */
        }
        print_time("dec", samples_encdec, NUM_ITER_ENCDEC);
        printf("\n");
    }

#endif


    if (!success)
        printf("Error!\n");
    return success ? 0 : 1;
}
Removed all .c and .h files files except bench.c from VS 2022 project and compiled without errors and got following results:
Please wait...
Below given minimal bench.c is working:


Is this a question or a statement?
Microsoft's compiler does not support this feature as far as I know.


Correct as for VS2022 with C17 support. This is on MS's list of 'to do things at some point' - but their emphasis is on C++ and not c.
https://developercommunity.visualstudio.com/t/about-arrys/402728

A 'quick and dirty' work-around is to use malloc (as c code):

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <stdlib.h>

int main() {
	int szx = 5;

	//int array[szx];
	int* array = malloc(szx * sizeof(int));
}


I know there's no free() but for a quick workaround the OS will free the memory allocated when the program terminates.
Last edited on
Thank you seeplus, for the excellent malloc idea.

I will work on this program, during next few weeks/months,
during my leisure time.

Again, thanks so much to all the developers for great ideas and help.


Last edited on
Topic archived. No new replies allowed.