2 * Copyright (C) 2014 Tobias Brunner
3 * Copyright (C) 2014 Andreas Steffen
5 * Copyright (C) secunet Security Networks AG
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "bliss_param_set.h"
25 typedef struct tuple_t tuple_t
;
35 typedef struct node_t node_t
;
47 static void print_node(node_t
*node
)
51 fprintf(stderr
, "(%1d,%2d)", node
->tuple
->z1
, node
->tuple
->z2
);
57 fprintf(stderr
, " %18.16f\n", node
->p
);
60 static double code_node(node_t
*node
, int *index
, uint8_t bits
, uint32_t code
)
62 double code_length
= 0;
64 node
->index
= (*index
)++;
68 node
->tuple
->code
= code
;
69 node
->tuple
->bits
= bits
;
70 code_length
+= node
->p
* bits
;
74 code_length
+= code_node(node
->l
, index
, bits
+ 1, (code
<< 1));
78 code_length
+= code_node(node
->r
, index
, bits
+ 1, (code
<< 1) + 1);
85 static void write_node(node_t
*node
)
87 int16_t node_0
, node_1
, tuple
;
89 node_0
= node
->l
? node
->l
->index
: BLISS_HUFFMAN_CODE_NO_NODE
;
90 node_1
= node
->r
? node
->r
->index
: BLISS_HUFFMAN_CODE_NO_NODE
;
91 tuple
= node
->tuple
? node
->tuple
->index
: BLISS_HUFFMAN_CODE_NO_TUPLE
;
93 printf("\t{ %3d, %3d, %3d }, /* %3d: ", node_0
, node_1
, tuple
, node
->index
);
97 printf("(%d,%2d) %2u bit%s ", node
->tuple
->z1
, node
->tuple
->z2
,
98 node
->tuple
->bits
, (node
->tuple
->bits
== 1) ? " " : "s");
112 static void write_header(void)
115 printf(" * Copyright (C) 2014 Andreas Steffen\n");
117 printf(" * Optimum Huffman code for BLISS-X signatures\n");
119 printf(" * This file has been automatically generated by the"
120 " bliss_huffman utility\n");
121 printf(" * Do not edit manually!\n");
125 static void write_code_tables(int bliss_type
, int n_z1
, int n_z2
, node_t
*nodes
,
132 printf("#include \"bliss_huffman_code.h\"\n\n");
134 printf("static bliss_huffman_code_node_t nodes[] = {\n");
136 code_length
= code_node(nodes
, &index
, 0, 0);
140 printf("static bliss_huffman_code_tuple_t tuples[] = {\n");
142 for (i
= 0; i
< n_z1
; i
++)
148 for (k
= 1 - n_z2
; k
< n_z2
; k
++)
150 printf("\t{ %5u, %2u }, /* %3d: (%1d,%2d) ",
151 tuples
[index
]->code
, tuples
[index
]->bits
, index
, i
, k
);
152 bit
= 1 << (tuples
[index
]->bits
- 1);
155 printf("%s", (tuples
[index
]->code
& bit
) ? "1" : "0");
163 printf("/* code_length = %6.4f bits/tuple (%d bits) */\n\n",
164 code_length
, (int)(512 * code_length
+ 1));
166 printf("bliss_huffman_code_t bliss_huffman_code_%d = {\n", bliss_type
);
167 printf("\t.n_z1 = %d,\n", n_z1
);
168 printf("\t.n_z2 = %d,\n", n_z2
);
169 printf("\t.tuples = tuples,\n");
170 printf("\t.nodes = nodes\n");
174 static void destroy_node(node_t
*node
)
178 destroy_node(node
->l
);
182 destroy_node(node
->r
);
188 static void remove_node(node_t
*list
, node_t
**last
, node_t
*node
)
190 node_t
*current
, *prev
;
192 for (current
= list
->next
, prev
= list
; current
;
193 prev
= current
, current
= current
->next
)
197 prev
->next
= current
->next
;
198 if (*last
== current
)
200 *last
= prev
->next
?: prev
;
208 * Generate a Huffman code for the optimum encoding of BLISS signatures
210 int main(int argc
, char *argv
[])
212 const bliss_param_set_t
*set
;
213 int dx
, bliss_type
, depth
= 1, groups
, groups_left
, pairs
= 1;
214 int i_max
= 9, k_max
= 8, index_max
= (2*k_max
- 1) * i_max
;
215 int i
, i_top
, k
, k_top
;
217 double p
, p_z1
[i_max
], p_z2
[k_max
], x_z1
[i_max
], x_z2
[k_max
];
218 double t
, x
, x0
, p_sum
, entropy
= 0, erf_i
, erf_k
, erf_0
= 0;
219 tuple_t
*tuple
, *tuples
[index_max
];
220 node_t
*node
, *node_l
, *node_r
, *nodes
= NULL
;
221 node_t
*node_list
, *node_last
;
225 fprintf(stderr
, "usage: bliss_huffman <bliss type> [<pairs>]\n");
230 pairs
= atoi(argv
[2]);
232 fprintf(stderr
, "%d code pairs with constant length\n\n", pairs
);
233 groups_left
= groups
= pairs
>> 1;
235 bliss_type
= atoi(argv
[1]);
236 set
= bliss_param_set_get_by_id(bliss_type
);
239 fprintf(stderr
, "bliss type %d unsupported\n", bliss_type
);
244 printf(" * Design: sigma = %u\n", set
->sigma
);
247 t
= 1/(sqrt(2) * set
->sigma
);
249 /* Probability distribution for z1 */
250 i_top
= (set
->B_inf
+ 255) / 256;
254 for (i
= 0; i
< i_top
; i
++)
256 x
= min(x
+ 256, set
->B_inf
);
258 p_z1
[i
] = erf_i
- erf_0
;
264 /* Normalize and print the probability distribution for z1 */
265 printf(" * i p_z1[i]\n");
268 for (i
= 0; i
< i_top
; i
++)
271 printf(" * %2d %18.16f %4.0f .. %4.0f\n", i
, p_z1
[i
], x0
, x_z1
[i
]);
276 /* Probability distribution for z2 */
278 k_top
= 1 + set
->B_inf
/ dx
;
282 for (k
= 0; k
< k_top
; k
++)
285 erf_k
= erf(t
*x
) / 2;
286 p_z2
[k
] = (k
== 0) ? 2*erf_k
: erf_k
- erf_0
;
287 p_sum
+= (k
== 0) ? p_z2
[k
] : 2*p_z2
[k
];
293 /* Normalize the probability distribution for z2 */
294 for (k
= 0; k
< k_top
; k
++)
299 /* Print the probability distribution for z2 */
300 printf(" * k p_z2[k] dx = %d\n", dx
);
302 for (k
= 1 - k_top
; k
< k_top
; k
++)
305 printf(" * %2d %18.16f ",k
, p_z2
[abs(k
)]);
308 printf(" %7.1f ..%7.1f\n", -x_z2
[-k
], -x_z2
[-k
-1]);
312 printf(" %7.1f ..%7.1f\n", -x_z2
[k
], x_z2
[k
]);
316 printf(" %7.1f ..%7.1f\n", x_z2
[k
-1], x_z2
[k
]);
321 /* Compute probabilities of tuples (z1, z2) */
323 node_last
= node_list
;
324 printf(" * (i, k) p\n");
328 for (i
= 0; i
< i_top
; i
++)
330 for (k
= 1 - k_top
; k
< k_top
; k
++)
332 p
= p_z1
[i
] * p_z2
[abs(k
)];
333 printf(" * (%1d,%2d) %18.16f\n", i
, k
, p
);
335 entropy
+= -log(p
) * p
;
342 tuples
[index
++] = tuple
;
348 node_last
->next
= node
;
354 printf(" * p_sum %18.16f\n", p_sum
);
356 printf(" * entropy = %6.4f bits/tuple (%d bits)\n",
357 entropy
, (int)(512 * entropy
));
360 /* Build Huffman tree */
361 while (node_list
->next
!= node_last
)
363 node_r
= node_l
= NULL
;
365 for (node
= node_list
->next
; node
; node
= node
->next
)
374 else if (groups_left
> 0)
376 if (node
->tuple
|| node
->depth
!= depth
)
381 if (node_r
== NULL
|| node
->p
< node_r
->p
)
386 else if (node_l
== NULL
|| node
->p
< node_l
->p
)
395 .p
= node_l
->p
+ node_r
->p
,
396 .depth
= 1 + max(node_l
->depth
, node_r
->depth
),
401 fprintf(stderr
, " %18.16f", node
->p
);
403 remove_node(node_list
, &node_last
, node_l
);
404 remove_node(node_list
, &node_last
, node_r
);
405 node_last
->next
= node
;
414 if (--groups_left
== 0)
417 groups_left
= groups
;
421 fprintf(stderr
, "\n\n");
425 nodes
= node_list
->next
;
427 write_code_tables(bliss_type
, i_top
, k_top
, nodes
, tuples
);
430 destroy_node(node_list
);