ec.c revision 1.1.1.2.4.1 1 1.1 christos /* apps/ec.c */
2 1.1 christos /*
3 1.1 christos * Written by Nils Larsch for the OpenSSL project.
4 1.1 christos */
5 1.1 christos /* ====================================================================
6 1.1 christos * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
7 1.1 christos *
8 1.1 christos * Redistribution and use in source and binary forms, with or without
9 1.1 christos * modification, are permitted provided that the following conditions
10 1.1 christos * are met:
11 1.1 christos *
12 1.1 christos * 1. Redistributions of source code must retain the above copyright
13 1.1.1.2.4.1 snj * notice, this list of conditions and the following disclaimer.
14 1.1 christos *
15 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 christos * notice, this list of conditions and the following disclaimer in
17 1.1 christos * the documentation and/or other materials provided with the
18 1.1 christos * distribution.
19 1.1 christos *
20 1.1 christos * 3. All advertising materials mentioning features or use of this
21 1.1 christos * software must display the following acknowledgment:
22 1.1 christos * "This product includes software developed by the OpenSSL Project
23 1.1 christos * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 1.1 christos *
25 1.1 christos * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 1.1 christos * endorse or promote products derived from this software without
27 1.1 christos * prior written permission. For written permission, please contact
28 1.1 christos * openssl-core (at) openssl.org.
29 1.1 christos *
30 1.1 christos * 5. Products derived from this software may not be called "OpenSSL"
31 1.1 christos * nor may "OpenSSL" appear in their names without prior written
32 1.1 christos * permission of the OpenSSL Project.
33 1.1 christos *
34 1.1 christos * 6. Redistributions of any form whatsoever must retain the following
35 1.1 christos * acknowledgment:
36 1.1 christos * "This product includes software developed by the OpenSSL Project
37 1.1 christos * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 1.1 christos *
39 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 1.1 christos * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 1.1 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 1.1 christos * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 1.1 christos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 1.1 christos * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 1.1 christos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 1.1 christos * OF THE POSSIBILITY OF SUCH DAMAGE.
51 1.1 christos * ====================================================================
52 1.1 christos *
53 1.1 christos * This product includes cryptographic software written by Eric Young
54 1.1 christos * (eay (at) cryptsoft.com). This product includes software written by Tim
55 1.1 christos * Hudson (tjh (at) cryptsoft.com).
56 1.1 christos *
57 1.1 christos */
58 1.1 christos
59 1.1 christos #include <openssl/opensslconf.h>
60 1.1 christos #ifndef OPENSSL_NO_EC
61 1.1.1.2.4.1 snj # include <stdio.h>
62 1.1.1.2.4.1 snj # include <stdlib.h>
63 1.1.1.2.4.1 snj # include <string.h>
64 1.1.1.2.4.1 snj # include "apps.h"
65 1.1.1.2.4.1 snj # include <openssl/bio.h>
66 1.1.1.2.4.1 snj # include <openssl/err.h>
67 1.1.1.2.4.1 snj # include <openssl/evp.h>
68 1.1.1.2.4.1 snj # include <openssl/pem.h>
69 1.1 christos
70 1.1.1.2.4.1 snj # undef PROG
71 1.1.1.2.4.1 snj # define PROG ec_main
72 1.1 christos
73 1.1.1.2.4.1 snj /*-
74 1.1.1.2.4.1 snj * -inform arg - input format - default PEM (one of DER, NET or PEM)
75 1.1 christos * -outform arg - output format - default PEM
76 1.1 christos * -in arg - input file - default stdin
77 1.1 christos * -out arg - output file - default stdout
78 1.1 christos * -des - encrypt output if PEM format with DES in cbc mode
79 1.1 christos * -text - print a text version
80 1.1 christos * -param_out - print the elliptic curve parameters
81 1.1 christos * -conv_form arg - specifies the point encoding form
82 1.1 christos * -param_enc arg - specifies the parameter encoding
83 1.1 christos */
84 1.1 christos
85 1.1 christos int MAIN(int, char **);
86 1.1 christos
87 1.1 christos int MAIN(int argc, char **argv)
88 1.1 christos {
89 1.1.1.2.4.1 snj int ret = 1;
90 1.1.1.2.4.1 snj EC_KEY *eckey = NULL;
91 1.1.1.2.4.1 snj const EC_GROUP *group;
92 1.1.1.2.4.1 snj int i, badops = 0;
93 1.1.1.2.4.1 snj const EVP_CIPHER *enc = NULL;
94 1.1.1.2.4.1 snj BIO *in = NULL, *out = NULL;
95 1.1.1.2.4.1 snj int informat, outformat, text = 0, noout = 0;
96 1.1.1.2.4.1 snj int pubin = 0, pubout = 0, param_out = 0;
97 1.1.1.2.4.1 snj char *infile, *outfile, *prog, *engine;
98 1.1.1.2.4.1 snj char *passargin = NULL, *passargout = NULL;
99 1.1.1.2.4.1 snj char *passin = NULL, *passout = NULL;
100 1.1.1.2.4.1 snj point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
101 1.1.1.2.4.1 snj int new_form = 0;
102 1.1.1.2.4.1 snj int asn1_flag = OPENSSL_EC_NAMED_CURVE;
103 1.1.1.2.4.1 snj int new_asn1_flag = 0;
104 1.1.1.2.4.1 snj
105 1.1.1.2.4.1 snj apps_startup();
106 1.1.1.2.4.1 snj
107 1.1.1.2.4.1 snj if (bio_err == NULL)
108 1.1.1.2.4.1 snj if ((bio_err = BIO_new(BIO_s_file())) != NULL)
109 1.1.1.2.4.1 snj BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
110 1.1.1.2.4.1 snj
111 1.1.1.2.4.1 snj if (!load_config(bio_err, NULL))
112 1.1.1.2.4.1 snj goto end;
113 1.1.1.2.4.1 snj
114 1.1.1.2.4.1 snj engine = NULL;
115 1.1.1.2.4.1 snj infile = NULL;
116 1.1.1.2.4.1 snj outfile = NULL;
117 1.1.1.2.4.1 snj informat = FORMAT_PEM;
118 1.1.1.2.4.1 snj outformat = FORMAT_PEM;
119 1.1.1.2.4.1 snj
120 1.1.1.2.4.1 snj prog = argv[0];
121 1.1.1.2.4.1 snj argc--;
122 1.1.1.2.4.1 snj argv++;
123 1.1.1.2.4.1 snj while (argc >= 1) {
124 1.1.1.2.4.1 snj if (strcmp(*argv, "-inform") == 0) {
125 1.1.1.2.4.1 snj if (--argc < 1)
126 1.1.1.2.4.1 snj goto bad;
127 1.1.1.2.4.1 snj informat = str2fmt(*(++argv));
128 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-outform") == 0) {
129 1.1.1.2.4.1 snj if (--argc < 1)
130 1.1.1.2.4.1 snj goto bad;
131 1.1.1.2.4.1 snj outformat = str2fmt(*(++argv));
132 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-in") == 0) {
133 1.1.1.2.4.1 snj if (--argc < 1)
134 1.1.1.2.4.1 snj goto bad;
135 1.1.1.2.4.1 snj infile = *(++argv);
136 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-out") == 0) {
137 1.1.1.2.4.1 snj if (--argc < 1)
138 1.1.1.2.4.1 snj goto bad;
139 1.1.1.2.4.1 snj outfile = *(++argv);
140 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-passin") == 0) {
141 1.1.1.2.4.1 snj if (--argc < 1)
142 1.1.1.2.4.1 snj goto bad;
143 1.1.1.2.4.1 snj passargin = *(++argv);
144 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-passout") == 0) {
145 1.1.1.2.4.1 snj if (--argc < 1)
146 1.1.1.2.4.1 snj goto bad;
147 1.1.1.2.4.1 snj passargout = *(++argv);
148 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-engine") == 0) {
149 1.1.1.2.4.1 snj if (--argc < 1)
150 1.1.1.2.4.1 snj goto bad;
151 1.1.1.2.4.1 snj engine = *(++argv);
152 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-noout") == 0)
153 1.1.1.2.4.1 snj noout = 1;
154 1.1.1.2.4.1 snj else if (strcmp(*argv, "-text") == 0)
155 1.1.1.2.4.1 snj text = 1;
156 1.1.1.2.4.1 snj else if (strcmp(*argv, "-conv_form") == 0) {
157 1.1.1.2.4.1 snj if (--argc < 1)
158 1.1.1.2.4.1 snj goto bad;
159 1.1.1.2.4.1 snj ++argv;
160 1.1.1.2.4.1 snj new_form = 1;
161 1.1.1.2.4.1 snj if (strcmp(*argv, "compressed") == 0)
162 1.1.1.2.4.1 snj form = POINT_CONVERSION_COMPRESSED;
163 1.1.1.2.4.1 snj else if (strcmp(*argv, "uncompressed") == 0)
164 1.1.1.2.4.1 snj form = POINT_CONVERSION_UNCOMPRESSED;
165 1.1.1.2.4.1 snj else if (strcmp(*argv, "hybrid") == 0)
166 1.1.1.2.4.1 snj form = POINT_CONVERSION_HYBRID;
167 1.1.1.2.4.1 snj else
168 1.1.1.2.4.1 snj goto bad;
169 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-param_enc") == 0) {
170 1.1.1.2.4.1 snj if (--argc < 1)
171 1.1.1.2.4.1 snj goto bad;
172 1.1.1.2.4.1 snj ++argv;
173 1.1.1.2.4.1 snj new_asn1_flag = 1;
174 1.1.1.2.4.1 snj if (strcmp(*argv, "named_curve") == 0)
175 1.1.1.2.4.1 snj asn1_flag = OPENSSL_EC_NAMED_CURVE;
176 1.1.1.2.4.1 snj else if (strcmp(*argv, "explicit") == 0)
177 1.1.1.2.4.1 snj asn1_flag = 0;
178 1.1.1.2.4.1 snj else
179 1.1.1.2.4.1 snj goto bad;
180 1.1.1.2.4.1 snj } else if (strcmp(*argv, "-param_out") == 0)
181 1.1.1.2.4.1 snj param_out = 1;
182 1.1.1.2.4.1 snj else if (strcmp(*argv, "-pubin") == 0)
183 1.1.1.2.4.1 snj pubin = 1;
184 1.1.1.2.4.1 snj else if (strcmp(*argv, "-pubout") == 0)
185 1.1.1.2.4.1 snj pubout = 1;
186 1.1.1.2.4.1 snj else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) {
187 1.1.1.2.4.1 snj BIO_printf(bio_err, "unknown option %s\n", *argv);
188 1.1.1.2.4.1 snj badops = 1;
189 1.1.1.2.4.1 snj break;
190 1.1.1.2.4.1 snj }
191 1.1.1.2.4.1 snj argc--;
192 1.1.1.2.4.1 snj argv++;
193 1.1.1.2.4.1 snj }
194 1.1.1.2.4.1 snj
195 1.1.1.2.4.1 snj if (badops) {
196 1.1.1.2.4.1 snj bad:
197 1.1.1.2.4.1 snj BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
198 1.1.1.2.4.1 snj BIO_printf(bio_err, "where options are\n");
199 1.1.1.2.4.1 snj BIO_printf(bio_err, " -inform arg input format - "
200 1.1.1.2.4.1 snj "DER or PEM\n");
201 1.1.1.2.4.1 snj BIO_printf(bio_err, " -outform arg output format - "
202 1.1.1.2.4.1 snj "DER or PEM\n");
203 1.1.1.2.4.1 snj BIO_printf(bio_err, " -in arg input file\n");
204 1.1.1.2.4.1 snj BIO_printf(bio_err, " -passin arg input file pass "
205 1.1.1.2.4.1 snj "phrase source\n");
206 1.1.1.2.4.1 snj BIO_printf(bio_err, " -out arg output file\n");
207 1.1.1.2.4.1 snj BIO_printf(bio_err, " -passout arg output file pass "
208 1.1.1.2.4.1 snj "phrase source\n");
209 1.1.1.2.4.1 snj BIO_printf(bio_err, " -engine e use engine e, "
210 1.1.1.2.4.1 snj "possibly a hardware device.\n");
211 1.1.1.2.4.1 snj BIO_printf(bio_err, " -des encrypt PEM output, "
212 1.1.1.2.4.1 snj "instead of 'des' every other \n"
213 1.1.1.2.4.1 snj " cipher "
214 1.1.1.2.4.1 snj "supported by OpenSSL can be used\n");
215 1.1.1.2.4.1 snj BIO_printf(bio_err, " -text print the key\n");
216 1.1.1.2.4.1 snj BIO_printf(bio_err, " -noout don't print key out\n");
217 1.1.1.2.4.1 snj BIO_printf(bio_err, " -param_out print the elliptic "
218 1.1.1.2.4.1 snj "curve parameters\n");
219 1.1.1.2.4.1 snj BIO_printf(bio_err, " -conv_form arg specifies the "
220 1.1.1.2.4.1 snj "point conversion form \n");
221 1.1.1.2.4.1 snj BIO_printf(bio_err, " possible values:"
222 1.1.1.2.4.1 snj " compressed\n");
223 1.1.1.2.4.1 snj BIO_printf(bio_err, " "
224 1.1.1.2.4.1 snj " uncompressed (default)\n");
225 1.1.1.2.4.1 snj BIO_printf(bio_err, " " " hybrid\n");
226 1.1.1.2.4.1 snj BIO_printf(bio_err, " -param_enc arg specifies the way"
227 1.1.1.2.4.1 snj " the ec parameters are encoded\n");
228 1.1.1.2.4.1 snj BIO_printf(bio_err, " in the asn1 der " "encoding\n");
229 1.1.1.2.4.1 snj BIO_printf(bio_err, " possible values:"
230 1.1.1.2.4.1 snj " named_curve (default)\n");
231 1.1.1.2.4.1 snj BIO_printf(bio_err, " "
232 1.1.1.2.4.1 snj "explicit\n");
233 1.1.1.2.4.1 snj goto end;
234 1.1.1.2.4.1 snj }
235 1.1 christos
236 1.1.1.2.4.1 snj ERR_load_crypto_strings();
237 1.1 christos
238 1.1.1.2.4.1 snj # ifndef OPENSSL_NO_ENGINE
239 1.1.1.2.4.1 snj setup_engine(bio_err, engine, 0);
240 1.1.1.2.4.1 snj # endif
241 1.1 christos
242 1.1.1.2.4.1 snj if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
243 1.1.1.2.4.1 snj BIO_printf(bio_err, "Error getting passwords\n");
244 1.1.1.2.4.1 snj goto end;
245 1.1.1.2.4.1 snj }
246 1.1.1.2.4.1 snj
247 1.1.1.2.4.1 snj in = BIO_new(BIO_s_file());
248 1.1.1.2.4.1 snj out = BIO_new(BIO_s_file());
249 1.1.1.2.4.1 snj if ((in == NULL) || (out == NULL)) {
250 1.1.1.2.4.1 snj ERR_print_errors(bio_err);
251 1.1.1.2.4.1 snj goto end;
252 1.1.1.2.4.1 snj }
253 1.1.1.2.4.1 snj
254 1.1.1.2.4.1 snj if (infile == NULL)
255 1.1.1.2.4.1 snj BIO_set_fp(in, stdin, BIO_NOCLOSE);
256 1.1.1.2.4.1 snj else {
257 1.1.1.2.4.1 snj if (BIO_read_filename(in, infile) <= 0) {
258 1.1.1.2.4.1 snj perror(infile);
259 1.1.1.2.4.1 snj goto end;
260 1.1.1.2.4.1 snj }
261 1.1.1.2.4.1 snj }
262 1.1.1.2.4.1 snj
263 1.1.1.2.4.1 snj BIO_printf(bio_err, "read EC key\n");
264 1.1.1.2.4.1 snj if (informat == FORMAT_ASN1) {
265 1.1.1.2.4.1 snj if (pubin)
266 1.1.1.2.4.1 snj eckey = d2i_EC_PUBKEY_bio(in, NULL);
267 1.1.1.2.4.1 snj else
268 1.1.1.2.4.1 snj eckey = d2i_ECPrivateKey_bio(in, NULL);
269 1.1.1.2.4.1 snj } else if (informat == FORMAT_PEM) {
270 1.1.1.2.4.1 snj if (pubin)
271 1.1.1.2.4.1 snj eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
272 1.1.1.2.4.1 snj else
273 1.1.1.2.4.1 snj eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin);
274 1.1.1.2.4.1 snj } else {
275 1.1.1.2.4.1 snj BIO_printf(bio_err, "bad input format specified for key\n");
276 1.1.1.2.4.1 snj goto end;
277 1.1.1.2.4.1 snj }
278 1.1.1.2.4.1 snj if (eckey == NULL) {
279 1.1.1.2.4.1 snj BIO_printf(bio_err, "unable to load Key\n");
280 1.1.1.2.4.1 snj ERR_print_errors(bio_err);
281 1.1.1.2.4.1 snj goto end;
282 1.1.1.2.4.1 snj }
283 1.1.1.2.4.1 snj
284 1.1.1.2.4.1 snj if (outfile == NULL) {
285 1.1.1.2.4.1 snj BIO_set_fp(out, stdout, BIO_NOCLOSE);
286 1.1.1.2.4.1 snj # ifdef OPENSSL_SYS_VMS
287 1.1.1.2.4.1 snj {
288 1.1.1.2.4.1 snj BIO *tmpbio = BIO_new(BIO_f_linebuffer());
289 1.1.1.2.4.1 snj out = BIO_push(tmpbio, out);
290 1.1.1.2.4.1 snj }
291 1.1.1.2.4.1 snj # endif
292 1.1.1.2.4.1 snj } else {
293 1.1.1.2.4.1 snj if (BIO_write_filename(out, outfile) <= 0) {
294 1.1.1.2.4.1 snj perror(outfile);
295 1.1.1.2.4.1 snj goto end;
296 1.1.1.2.4.1 snj }
297 1.1.1.2.4.1 snj }
298 1.1.1.2.4.1 snj
299 1.1.1.2.4.1 snj group = EC_KEY_get0_group(eckey);
300 1.1.1.2.4.1 snj
301 1.1.1.2.4.1 snj if (new_form)
302 1.1.1.2.4.1 snj EC_KEY_set_conv_form(eckey, form);
303 1.1.1.2.4.1 snj
304 1.1.1.2.4.1 snj if (new_asn1_flag)
305 1.1.1.2.4.1 snj EC_KEY_set_asn1_flag(eckey, asn1_flag);
306 1.1.1.2.4.1 snj
307 1.1.1.2.4.1 snj if (text)
308 1.1.1.2.4.1 snj if (!EC_KEY_print(out, eckey, 0)) {
309 1.1.1.2.4.1 snj perror(outfile);
310 1.1.1.2.4.1 snj ERR_print_errors(bio_err);
311 1.1.1.2.4.1 snj goto end;
312 1.1.1.2.4.1 snj }
313 1.1.1.2.4.1 snj
314 1.1.1.2.4.1 snj if (noout) {
315 1.1.1.2.4.1 snj ret = 0;
316 1.1.1.2.4.1 snj goto end;
317 1.1.1.2.4.1 snj }
318 1.1.1.2.4.1 snj
319 1.1.1.2.4.1 snj BIO_printf(bio_err, "writing EC key\n");
320 1.1.1.2.4.1 snj if (outformat == FORMAT_ASN1) {
321 1.1.1.2.4.1 snj if (param_out)
322 1.1.1.2.4.1 snj i = i2d_ECPKParameters_bio(out, group);
323 1.1.1.2.4.1 snj else if (pubin || pubout)
324 1.1.1.2.4.1 snj i = i2d_EC_PUBKEY_bio(out, eckey);
325 1.1.1.2.4.1 snj else
326 1.1.1.2.4.1 snj i = i2d_ECPrivateKey_bio(out, eckey);
327 1.1.1.2.4.1 snj } else if (outformat == FORMAT_PEM) {
328 1.1.1.2.4.1 snj if (param_out)
329 1.1.1.2.4.1 snj i = PEM_write_bio_ECPKParameters(out, group);
330 1.1.1.2.4.1 snj else if (pubin || pubout)
331 1.1.1.2.4.1 snj i = PEM_write_bio_EC_PUBKEY(out, eckey);
332 1.1.1.2.4.1 snj else
333 1.1.1.2.4.1 snj i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
334 1.1.1.2.4.1 snj NULL, 0, NULL, passout);
335 1.1.1.2.4.1 snj } else {
336 1.1.1.2.4.1 snj BIO_printf(bio_err, "bad output format specified for " "outfile\n");
337 1.1.1.2.4.1 snj goto end;
338 1.1.1.2.4.1 snj }
339 1.1.1.2.4.1 snj
340 1.1.1.2.4.1 snj if (!i) {
341 1.1.1.2.4.1 snj BIO_printf(bio_err, "unable to write private key\n");
342 1.1.1.2.4.1 snj ERR_print_errors(bio_err);
343 1.1.1.2.4.1 snj } else
344 1.1.1.2.4.1 snj ret = 0;
345 1.1.1.2.4.1 snj end:
346 1.1.1.2.4.1 snj if (in)
347 1.1.1.2.4.1 snj BIO_free(in);
348 1.1.1.2.4.1 snj if (out)
349 1.1.1.2.4.1 snj BIO_free_all(out);
350 1.1.1.2.4.1 snj if (eckey)
351 1.1.1.2.4.1 snj EC_KEY_free(eckey);
352 1.1.1.2.4.1 snj if (passin)
353 1.1.1.2.4.1 snj OPENSSL_free(passin);
354 1.1.1.2.4.1 snj if (passout)
355 1.1.1.2.4.1 snj OPENSSL_free(passout);
356 1.1.1.2.4.1 snj apps_shutdown();
357 1.1.1.2.4.1 snj OPENSSL_EXIT(ret);
358 1.1 christos }
359 1.1.1.2.4.1 snj #else /* !OPENSSL_NO_EC */
360 1.1 christos
361 1.1 christos # if PEDANTIC
362 1.1.1.2.4.1 snj static void *dummy = &dummy;
363 1.1 christos # endif
364 1.1 christos
365 1.1 christos #endif
366