~ubuntu-branches/ubuntu/natty/libgcrypt11/natty-proposed

« back to all changes in this revision

Viewing changes to cipher/ecc.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2009-02-21 13:46:58 UTC
  • mto: (1.1.6 upstream) (2.1.3 squeeze)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20090221134658-855twvcr4ezk2ron
ImportĀ upstreamĀ versionĀ 1.4.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* ecc.c  -  Elliptic Curve Cryptography
2
 
   Copyright (C) 2007 Free Software Foundation, Inc.
 
2
   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
3
3
 
4
4
   This file is part of Libgcrypt.
5
5
  
54
54
#include <stdio.h>
55
55
#include <stdlib.h>
56
56
#include <string.h>
57
 
#include <assert.h>
58
57
 
59
58
#include "g10lib.h"
60
59
#include "mpi.h"
128
127
{
129
128
  const char *desc;           /* Description of the curve.  */
130
129
  unsigned int nbits;         /* Number of bits.  */
 
130
  unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
131
131
  const char  *p;             /* Order of the prime field.  */
132
132
  const char *a, *b;          /* The coefficients. */
133
133
  const char *n;              /* The order of the base point.  */
135
135
} domain_parms[] =
136
136
  {
137
137
    {
138
 
      "NIST P-192", 192,
 
138
      "NIST P-192", 192, 1,
139
139
      "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
140
140
      "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
141
141
      "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
145
145
      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
146
146
    },
147
147
    {
148
 
      "NIST P-224", 224,
 
148
      "NIST P-224", 224, 1,
149
149
      "0xffffffffffffffffffffffffffffffff000000000000000000000001",
150
150
      "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
151
151
      "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
155
155
      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
156
156
    },
157
157
    {
158
 
      "NIST P-256", 256,
 
158
      "NIST P-256", 256, 1,
159
159
      "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
160
160
      "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
161
161
      "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
165
165
      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
166
166
    },
167
167
    {
168
 
      "NIST P-384", 384,
 
168
      "NIST P-384", 384, 1,
169
169
      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
170
170
      "ffffffff0000000000000000ffffffff",
171
171
      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
181
181
      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
182
182
    },
183
183
    {
184
 
      "NIST P-521", 521,
 
184
      "NIST P-521", 521, 1,
185
185
      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
186
186
      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
187
187
      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
197
197
      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
198
198
    },
199
199
 
200
 
    { "brainpoolP160r1", 160,
 
200
    { "brainpoolP160r1", 160, 0, 
201
201
      "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
202
202
      "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
203
203
      "0x1e589a8595423412134faa2dbdec95c8d8675e58",
206
206
      "0x1667cb477a1a8ec338f94741669c976316da6321"
207
207
    },
208
208
 
209
 
    { "brainpoolP192r1", 192,
 
209
    { "brainpoolP192r1", 192, 0, 
210
210
      "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
211
211
      "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
212
212
      "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
215
215
      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
216
216
    },
217
217
 
218
 
    { "brainpoolP224r1", 224,
 
218
    { "brainpoolP224r1", 224, 0,
219
219
      "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
220
220
      "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
221
221
      "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
224
224
      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
225
225
    },
226
226
 
227
 
    { "brainpoolP256r1", 256, 
 
227
    { "brainpoolP256r1", 256, 0,
228
228
      "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
229
229
      "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
230
230
      "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
233
233
      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
234
234
    },
235
235
 
236
 
    { "brainpoolP320r1", 320, 
 
236
    { "brainpoolP320r1", 320, 0,
237
237
      "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
238
238
      "fcd412b1f1b32e27",
239
239
      "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
248
248
      "d35245d1692e8ee1"
249
249
    },
250
250
 
251
 
    { "brainpoolP384r1", 384, 
 
251
    { "brainpoolP384r1", 384, 0,
252
252
      "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
253
253
      "acd3a729901d1a71874700133107ec53",
254
254
      "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
263
263
      "0e4646217791811142820341263c5315"
264
264
    },
265
265
 
266
 
    { "brainpoolP512r1", 512,
 
266
    { "brainpoolP512r1", 512, 0,
267
267
      "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
268
268
      "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
269
269
      "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
278
278
      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
279
279
    },
280
280
 
281
 
    { NULL, 0, NULL, NULL, NULL, NULL }
 
281
    { NULL, 0, 0, NULL, NULL, NULL, NULL }
282
282
  };
283
283
 
284
284
 
478
478
  if (!domain_parms[idx].desc)
479
479
    return GPG_ERR_INV_VALUE;
480
480
 
 
481
  /* In fips mode we only support NIST curves.  Note that it is
 
482
     possible to bypass this check by specifying the curve parameters
 
483
     directly.  */
 
484
  if (fips_mode () && !domain_parms[idx].fips )
 
485
    return GPG_ERR_NOT_SUPPORTED; 
 
486
  
 
487
 
481
488
  *r_nbits = domain_parms[idx].nbits;
482
489
  curve->p = scanval (domain_parms[idx].p);
483
490
  curve->a = scanval (domain_parms[idx].a);
942
949
  return 0;
943
950
}
944
951
 
945
 
/* Extended version of ecc_generate which is called directly by
946
 
   pubkey.c.  If CURVE is not NULL, that name will be used to select
947
 
   the domain parameters.  NBITS is not used in this case.  */
948
 
gcry_err_code_t
949
 
_gcry_ecc_generate (int algo, unsigned int nbits, const char *curve,
950
 
                    gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 
952
 
 
953
/* Extended version of ecc_generate.  */
 
954
static gcry_err_code_t
 
955
ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
 
956
                  const gcry_sexp_t genparms,
 
957
                  gcry_mpi_t *skey, gcry_mpi_t **retfactors,
 
958
                  gcry_sexp_t *r_extrainfo)
951
959
{
952
 
  gpg_err_code_t err;
 
960
  gpg_err_code_t ec;
953
961
  ECC_secret_key sk;
954
962
  gcry_mpi_t g_x, g_y, q_x, q_y;
 
963
  char *curve_name = NULL;
 
964
  gcry_sexp_t l1;
955
965
 
956
966
  (void)algo;
957
 
 
958
 
  /* Make an empty list of factors.  */
959
 
  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
960
 
  if (!*retfactors)
961
 
    return gpg_err_code_from_syserror ();
 
967
  (void)evalue;
 
968
  (void)r_extrainfo;
 
969
 
 
970
  if (genparms)
 
971
    {
 
972
      /* Parse the optional "curve" parameter. */
 
973
      l1 = gcry_sexp_find_token (genparms, "curve", 0);
 
974
      if (l1)
 
975
        {
 
976
          curve_name = _gcry_sexp_nth_string (l1, 1);
 
977
          gcry_sexp_release (l1);
 
978
          if (!curve_name)
 
979
            return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
 
980
        }
 
981
    }
 
982
 
 
983
  /* NBITS is required if no curve name has been given.  */
 
984
  if (!nbits && !curve_name)
 
985
    return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
962
986
 
963
987
  g_x = mpi_new (0);
964
988
  g_y = mpi_new (0);
965
989
  q_x = mpi_new (0);
966
990
  q_y = mpi_new (0);
967
 
  err = generate_key (&sk, nbits, curve, g_x, g_y, q_x, q_y);
968
 
  if (err)
969
 
    {
970
 
      gcry_free (*retfactors);
971
 
      *retfactors = NULL;
972
 
      return err;
973
 
    }
 
991
  ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y);
 
992
  gcry_free (curve_name);
 
993
  if (ec)
 
994
    return ec;
974
995
 
975
996
  skey[0] = sk.E.p;
976
997
  skey[1] = sk.E.a;
985
1006
  point_free (&sk.E.G);
986
1007
  point_free (&sk.Q);
987
1008
 
 
1009
  /* Make an empty list of factors.  */
 
1010
  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
 
1011
  if (!*retfactors)
 
1012
    return gpg_err_code_from_syserror ();
 
1013
 
988
1014
  return 0;
989
1015
}
990
1016
 
 
1017
 
 
1018
static gcry_err_code_t
 
1019
ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
 
1020
              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 
1021
{
 
1022
  (void)evalue;
 
1023
  return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
 
1024
}
 
1025
 
 
1026
 
991
1027
/* Return the parameters of the curve NAME.  */
992
 
gcry_err_code_t
993
 
_gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
 
1028
static gcry_err_code_t
 
1029
ecc_get_param (const char *name, gcry_mpi_t *pkey)
994
1030
{
995
1031
  gpg_err_code_t err;
996
1032
  unsigned int nbits;
1020
1056
  return 0;
1021
1057
}
1022
1058
 
1023
 
static gcry_err_code_t
1024
 
ecc_generate (int algo, unsigned int nbits, unsigned long dummy,
1025
 
              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
1026
 
{
1027
 
  (void)dummy;
1028
 
  return _gcry_ecc_generate (algo, nbits, NULL, skey, retfactors);
1029
 
}
1030
 
 
1031
1059
 
1032
1060
static gcry_err_code_t
1033
1061
ecc_check_secret_key (int algo, gcry_mpi_t *skey)
1175
1203
}
1176
1204
 
1177
1205
 
 
1206
 
 
1207
/* See rsa.c for a description of this function.  */
 
1208
static gpg_err_code_t
 
1209
compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
 
1210
{
 
1211
  static const char names[] = "pabgnq";
 
1212
  gpg_err_code_t ec = 0;
 
1213
  gcry_sexp_t l1;
 
1214
  gcry_mpi_t values[6];
 
1215
  int idx;
 
1216
 
 
1217
  /* Clear the values for easier error cleanup.  */
 
1218
  for (idx=0; idx < 6; idx++)
 
1219
    values[idx] = NULL;
 
1220
    
 
1221
  /* Fill values with all available parameters.  */
 
1222
  for (idx=0; idx < 6; idx++)
 
1223
    {
 
1224
      l1 = gcry_sexp_find_token (keyparam, names+idx, 1);
 
1225
      if (l1)
 
1226
        {
 
1227
          values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
 
1228
          gcry_sexp_release (l1);
 
1229
          if (!values[idx])
 
1230
            {
 
1231
              ec = GPG_ERR_INV_OBJ;
 
1232
              goto leave;
 
1233
            }
 
1234
        }
 
1235
    }
 
1236
  
 
1237
  /* Check whether a curve parameter is available and use that to fill
 
1238
     in missing values.  */
 
1239
  l1 = gcry_sexp_find_token (keyparam, "curve", 5);
 
1240
  if (l1)
 
1241
    {
 
1242
      char *curve;
 
1243
      gcry_mpi_t tmpvalues[6];
 
1244
      
 
1245
      for (idx = 0; idx < 6; idx++)
 
1246
        tmpvalues[idx] = NULL;
 
1247
 
 
1248
      curve = _gcry_sexp_nth_string (l1, 1);
 
1249
      if (!curve)
 
1250
        {
 
1251
          ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
 
1252
          goto leave;
 
1253
        }
 
1254
      ec = ecc_get_param (curve, tmpvalues);
 
1255
      gcry_free (curve);
 
1256
      if (ec)
 
1257
        goto leave;
 
1258
 
 
1259
      for (idx = 0; idx < 6; idx++)
 
1260
        {
 
1261
          if (!values[idx])
 
1262
            values[idx] = tmpvalues[idx];
 
1263
          else
 
1264
            mpi_free (tmpvalues[idx]);
 
1265
        }
 
1266
    }
 
1267
 
 
1268
  /* Check that all parameters are known and normalize all MPIs (that
 
1269
     should not be required but we use an internal fucntion later and
 
1270
     thus we better make 100% sure that they are normalized). */
 
1271
  for (idx = 0; idx < 6; idx++)
 
1272
    if (!values[idx])
 
1273
      {
 
1274
        ec = GPG_ERR_NO_OBJ;
 
1275
        goto leave;
 
1276
      }
 
1277
    else
 
1278
      _gcry_mpi_normalize (values[idx]);
 
1279
      
 
1280
  /* Hash them all.  */
 
1281
  for (idx = 0; idx < 6; idx++)
 
1282
    {
 
1283
      char buf[30];
 
1284
      unsigned char *rawmpi;
 
1285
      unsigned int rawmpilen;
 
1286
      
 
1287
      rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL);
 
1288
      if (!rawmpi)
 
1289
        {
 
1290
          ec = gpg_err_code_from_syserror ();
 
1291
          goto leave;
 
1292
        }
 
1293
      snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
 
1294
      gcry_md_write (md, buf, strlen (buf));
 
1295
      gcry_md_write (md, rawmpi, rawmpilen);
 
1296
      gcry_md_write (md, ")", 1);
 
1297
      gcry_free (rawmpi);
 
1298
    }
 
1299
 
 
1300
 leave:
 
1301
  for (idx = 0; idx < 6; idx++)
 
1302
    _gcry_mpi_release (values[idx]);
 
1303
  
 
1304
  return ec;
 
1305
}
 
1306
 
 
1307
 
 
1308
 
 
1309
 
 
1310
 
 
1311
/* 
 
1312
     Self-test section.
 
1313
 */
 
1314
 
 
1315
 
 
1316
static gpg_err_code_t
 
1317
selftests_ecdsa (selftest_report_func_t report)
 
1318
{
 
1319
  const char *what;
 
1320
  const char *errtxt;
 
1321
  
 
1322
  what = "low-level";
 
1323
  errtxt = NULL; /*selftest ();*/
 
1324
  if (errtxt)
 
1325
    goto failed;
 
1326
 
 
1327
  /* FIXME:  need more tests.  */
 
1328
 
 
1329
  return 0; /* Succeeded. */
 
1330
 
 
1331
 failed:
 
1332
  if (report)
 
1333
    report ("pubkey", GCRY_PK_ECDSA, what, errtxt);
 
1334
  return GPG_ERR_SELFTEST_FAILED;
 
1335
}
 
1336
 
 
1337
 
 
1338
/* Run a full self-test for ALGO and return 0 on success.  */
 
1339
static gpg_err_code_t
 
1340
run_selftests (int algo, int extended, selftest_report_func_t report)
 
1341
{
 
1342
  gpg_err_code_t ec;
 
1343
 
 
1344
  (void)extended;
 
1345
 
 
1346
  switch (algo)
 
1347
    {
 
1348
    case GCRY_PK_ECDSA:
 
1349
      ec = selftests_ecdsa (report);
 
1350
      break;
 
1351
    default:
 
1352
      ec = GPG_ERR_PUBKEY_ALGO;
 
1353
      break;
 
1354
        
 
1355
    }
 
1356
  return ec;
 
1357
}
 
1358
 
 
1359
 
 
1360
 
 
1361
 
1178
1362
static const char *ecdsa_names[] =
1179
1363
  {
1180
1364
    "ecdsa",
1196
1380
    ecc_get_nbits
1197
1381
  };
1198
1382
 
 
1383
pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = 
 
1384
  {
 
1385
    run_selftests,
 
1386
    ecc_generate_ext,
 
1387
    compute_keygrip,
 
1388
    ecc_get_param
 
1389
  };
 
1390