/**************** * Find the greatest common divisor G of A and B. * Return: true if this 1, false in all other cases */ int mpi_gcd( MPI g, const MPI xa, const MPI xb ) { MPI a = NULL, b = NULL; if (mpi_copy(&a, xa) < 0) goto nomem; if (mpi_copy(&b, xb) < 0) goto nomem; /* TAOCP Vol II, 4.5.2, Algorithm A */ a->sign = 0; b->sign = 0; while( mpi_cmp_ui( b, 0 ) ) { if (mpi_fdiv_r( g, a, b ) < 0) /* g used as temorary variable */ goto nomem; if (mpi_set(a,b) < 0) goto nomem; if (mpi_set(b,g) < 0) goto nomem; } if (mpi_set(g, a) < 0) goto nomem; mpi_free(a); mpi_free(b); return !mpi_cmp_ui( g, 1); nomem: mpi_free(a); mpi_free(b); return -ENOMEM; }
/* This function initialized a context for elliptic curve based on the field GF(p). P is the prime specifying this field, A is the first coefficient. CTX is expected to be zeroized. */ static void ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a) { int i; /* Fixme: Do we want to check some constraints? e.g. a < p */ ctx->p = mpi_copy (p); ctx->a = mpi_copy (a); ec_get_reset (ctx); /* Allocate scratch variables. */ for (i=0; i< DIM(ctx->t.scratch); i++) ctx->t.scratch[i] = mpi_alloc_like (ctx->p); /* Prepare for fast reduction. */ /* FIXME: need a test for NIST values. However it does not gain us any real advantage, for 384 bits it is actually slower than using mpi_mulm. */ /* ctx->nist_nbits = mpi_get_nbits (ctx->p); */ /* if (ctx->nist_nbits == 192) */ /* { */ /* for (i=0; i < 4; i++) */ /* ctx->s[i] = mpi_new (192); */ /* ctx->c = mpi_new (192*2); */ /* } */ /* else if (ctx->nist_nbits == 384) */ /* { */ /* for (i=0; i < 10; i++) */ /* ctx->s[i] = mpi_new (384); */ /* ctx->c = mpi_new (384*2); */ /* } */ }
/* Return an MPI (or opaque MPI) described by NAME and the context EC. If COPY is true a copy is returned, if not a const MPI may be returned. In any case mpi_free must be used. */ gcry_mpi_t _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy) { if (!*name) return NULL; if (!strcmp (name, "p") && ec->p) return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p); if (!strcmp (name, "a") && ec->a) return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a); if (!strcmp (name, "b") && ec->b) return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b); if (!strcmp (name, "n") && ec->n) return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n); if (!strcmp (name, "d") && ec->d) return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d); /* Return a requested point coordinate. */ if (!strcmp (name, "g.x") && ec->G && ec->G->x) return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x); if (!strcmp (name, "g.y") && ec->G && ec->G->y) return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y); if (!strcmp (name, "q.x") && ec->Q && ec->Q->x) return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x); if (!strcmp (name, "q.y") && ec->Q && ec->Q->y) return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y); /* If the base point has been requested, return it in standard encoding. */ if (!strcmp (name, "g") && ec->G) return _gcry_mpi_ec_ec2os (ec->G, ec); /* If the public key has been requested, return it by default in standard uncompressed encoding or if requested in other encodings. */ if (*name == 'q' && (!name[1] || name[1] == '@')) { /* If only the private key is given, compute the public key. */ if (!ec->Q) ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL); if (!ec->Q) return NULL; if (name[1] != '@') return _gcry_mpi_ec_ec2os (ec->Q, ec); if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_TWISTEDEDWARDS) { unsigned char *encpk; unsigned int encpklen; if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, &encpk, &encpklen)) return mpi_set_opaque (NULL, encpk, encpklen*8); } } return NULL; }
/* * Return a copy of a curve object. */ static elliptic_curve_t curve_copy (elliptic_curve_t E) { elliptic_curve_t R; R.p = mpi_copy (E.p); R.a = mpi_copy (E.a); R.b = mpi_copy (E.b); point_init (&R.G); point_set (&R.G, &E.G); R.n = mpi_copy (E.n); return R; }
int mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ) { int rc = -ENOMEM; int divisor_sign = divisor->sign; MPI temp_divisor = NULL; /* We need the original value of the divisor after the remainder has been * preliminary calculated. We have to copy it to temporary space if it's * the same variable as REM. */ if( rem == divisor ) { if (mpi_copy( &temp_divisor, divisor ) < 0) goto nomem; divisor = temp_divisor; } if (mpi_tdiv_qr(NULL, rem, dividend, divisor ) < 0) goto nomem; if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) if (mpi_add( rem, rem, divisor) < 0) goto nomem; rc = 0; nomem: if( temp_divisor ) mpi_free(temp_divisor); return rc; }
/* This function returns a new context for Barrett based operations on the modulus M. This context needs to be released using _gcry_mpi_barrett_free. If COPY is true M will be transferred to the context and the user may change M. If COPY is false, M may not be changed until gcry_mpi_barrett_free has been called. */ mpi_barrett_t _gcry_mpi_barrett_init (gcry_mpi_t m, int copy) { mpi_barrett_t ctx; gcry_mpi_t tmp; mpi_normalize (m); ctx = xcalloc (1, sizeof *ctx); if (copy) { ctx->m = mpi_copy (m); ctx->m_copied = 1; } else ctx->m = m; ctx->k = mpi_get_nlimbs (m); tmp = mpi_alloc (ctx->k + 1); /* Barrett precalculation: y = floor(b^(2k) / m). */ mpi_set_ui (tmp, 1); mpi_lshift_limbs (tmp, 2 * ctx->k); mpi_fdiv_q (tmp, tmp, m); ctx->y = tmp; ctx->r1 = mpi_alloc ( 2 * ctx->k + 1 ); ctx->r2 = mpi_alloc ( 2 * ctx->k + 1 ); return ctx; }
int mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ) { int divisor_sign = divisor->sign; MPI temp_divisor = NULL; if( quot == divisor || rem == divisor ) { if (mpi_copy( &temp_divisor, divisor ) < 0) return -ENOMEM; divisor = temp_divisor; } if (mpi_tdiv_qr( quot, rem, dividend, divisor ) < 0) goto nomem; if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { if (mpi_sub_ui( quot, quot, 1 ) < 0) goto nomem; if (mpi_add( rem, rem, divisor) < 0) goto nomem; } if( temp_divisor ) mpi_free(temp_divisor); return 0; nomem: mpi_free(temp_divisor); return -ENOMEM; }
/* * Compute shared secret (SEC1 3.3.1) */ int ecdh_compute_shared( ecp_group *grp, mpi *z, const ecp_point *Q, const mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; ecp_point P; ecp_point_init( &P ); /* * Make sure Q is a valid pubkey before using it */ MPI_CHK( ecp_check_pubkey( grp, Q ) ); MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); if( ecp_is_zero( &P ) ) { ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } MPI_CHK( mpi_copy( z, &P.X ) ); cleanup: ecp_point_free( &P ); return( ret ); }
/* * Generate or update blinding values, see section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, * DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer * Berlin Heidelberg, 1996. p. 104-113. */ static int rsa_prepare_blinding( rsa_context *ctx, mpi *Vi, mpi *Vf, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, count = 0; #if defined(POLARSSL_THREADING_C) polarssl_mutex_lock( &ctx->mutex ); #endif if( ctx->Vf.p != NULL ) { /* We already have blinding values, just update them by squaring */ MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); goto done; } /* Unblinding value: Vf = random number, invertible mod N */ do { if( count++ > 10 ) return( POLARSSL_ERR_RSA_RNG_FAILED ); MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); MPI_CHK( mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); } while( mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); /* Blinding value: Vi = Vf^(-e) mod N */ MPI_CHK( mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); MPI_CHK( mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); done: if( Vi != &ctx->Vi ) { MPI_CHK( mpi_copy( Vi, &ctx->Vi ) ); MPI_CHK( mpi_copy( Vf, &ctx->Vf ) ); } cleanup: #if defined(POLARSSL_THREADING_C) polarssl_mutex_unlock( &ctx->mutex ); #endif return( ret ); }
/* * Return a copy of a curve object. */ elliptic_curve_t _gcry_ecc_curve_copy (elliptic_curve_t E) { elliptic_curve_t R; R.model = E.model; R.dialect = E.dialect; R.name = E.name; R.p = mpi_copy (E.p); R.a = mpi_copy (E.a); R.b = mpi_copy (E.b); _gcry_mpi_point_init (&R.G); point_set (&R.G, &E.G); R.n = mpi_copy (E.n); return R; }
void gcry_mpi_sub(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) { gcry_mpi_t vv = mpi_copy (v); vv->sign = ! vv->sign; gcry_mpi_add (w, u, vv); mpi_free (vv); }
int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial ) { int ret; if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 ) return( ret ); return( 0 ); }
gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); if (!strcmp (name, "p") && ec->p) return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p); if (!strcmp (name, "a") && ec->a) return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a); if (!strcmp (name, "b") && ec->b) return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b); if (!strcmp (name, "n") && ec->n) return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n); if (!strcmp (name, "d") && ec->d) return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d); /* Return a requested point coordinate. */ if (!strcmp (name, "g.x") && ec->G && ec->G->x) return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x); if (!strcmp (name, "g.y") && ec->G && ec->G->y) return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y); if (!strcmp (name, "q.x") && ec->Q && ec->Q->x) return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x); if (!strcmp (name, "q.y") && ec->Q && ec->Q->y) return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y); /* If a point has been requested, return it in standard encoding. */ if (!strcmp (name, "g") && ec->G) return _gcry_mpi_ec_ec2os (ec->G, ec); if (!strcmp (name, "q")) { /* If only the private key is given, compute the public key. */ if (!ec->Q && ec->d && ec->G && ec->p && ec->a) { ec->Q = gcry_mpi_point_new (0); _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec); } if (ec->Q) return _gcry_mpi_ec_ec2os (ec->Q, ec); } return NULL; }
/**************** * Find the greatest common divisor G of A and B. * Return: true if this 1, false in all other cases */ int mpi_gcd( MPI g, MPI xa, MPI xb ) { MPI a, b; a = mpi_copy(xa); b = mpi_copy(xb); /* TAOCP Vol II, 4.5.2, Algorithm A */ a->sign = 0; b->sign = 0; while( mpi_cmp_ui( b, 0 ) ) { mpi_fdiv_r( g, a, b ); /* g used as temorary variable */ mpi_set(a,b); mpi_set(b,g); } mpi_set(g, a); mpi_free(a); mpi_free(b); return !mpi_cmp_ui( g, 1); }
gpg_err_code_t _gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue, gcry_ctx_t ctx) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); if (!strcmp (name, "p")) { mpi_free (ec->p); ec->p = mpi_copy (newvalue); ec_get_reset (ec); } else if (!strcmp (name, "a")) { mpi_free (ec->a); ec->a = mpi_copy (newvalue); ec_get_reset (ec); } else if (!strcmp (name, "b")) { mpi_free (ec->b); ec->b = mpi_copy (newvalue); } else if (!strcmp (name, "n")) { mpi_free (ec->n); ec->n = mpi_copy (newvalue); } else if (!strcmp (name, "d")) { mpi_free (ec->d); ec->d = mpi_copy (newvalue); } else return GPG_ERR_UNKNOWN_NAME; return 0; }
result_t PKey::copy(const pk_context &key) { pk_type_t type = pk_get_type(&key); int ret; if (type == POLARSSL_PK_RSA) { rsa_context *rsa = pk_rsa(key); ret = pk_init_ctx(&m_key, pk_info_from_type(POLARSSL_PK_RSA)); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); rsa_context *rsa1 = pk_rsa(m_key); ret = rsa_copy(rsa1, rsa); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); return 0; } if (type == POLARSSL_PK_ECKEY) { ecp_keypair *ecp = pk_ec(key); ret = pk_init_ctx(&m_key, pk_info_from_type(POLARSSL_PK_ECKEY)); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); ecp_keypair *ecp1 = pk_ec(m_key); ret = ecp_group_copy(&ecp1->grp, &ecp->grp); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); ret = mpi_copy(&ecp1->d, &ecp->d); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); ret = ecp_copy(&ecp1->Q, &ecp->Q); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); return 0; } return CHECK_ERROR(CALL_E_INVALID_CALL); }
void mpi_sub(MPI w, MPI u, MPI v) { if( w == v ) { MPI vv = mpi_copy(v); vv->sign = !vv->sign; mpi_add( w, u, vv ); mpi_free(vv); } else { /* fixme: this is not thread-save (we temp. modify v) */ v->sign = !v->sign; mpi_add( w, u, v ); v->sign = !v->sign; } }
void Init_Direct_Mode(mp_image_t *mpi) { if ((LCD_OUT & display_mode) == TV_OUT) { img_param.ipu_d_fmt |= (OUT_FMT_YUV422 | (1 << 16)); img_param.in_bpp = 16; } else { img_param.ipu_d_fmt |= OUT_FMT_RGB888; img_param.in_bpp = 32; } if(display_mode & DECODE_BUFFER) { img_param.y_buf = mpi->planes[0]; img_param.u_buf = mpi->planes[1]; img_param.v_buf = mpi->planes[2]; stride.y = mpi->stride[0]; stride.u = mpi->stride[1]; stride.v = mpi->stride[2]; lcd_flush_frame_all(); jz47_put_image_with_ipu = jz47_put_image_with_direct_ipu_nobuffer; printf("direct buf\n"); }else { CreateImage(mpi->width,mpi->height,mpi->chroma_width,mpi->chroma_height,mpi->bpp); mpi_copy(yuv_cur,mpi); img_param.y_buf = yuv_cur->y_framebuf; img_param.u_buf = yuv_cur->u_framebuf; img_param.v_buf = yuv_cur->v_framebuf; stride.y = yuv_cur->ystride; stride.u = yuv_cur->ustride; stride.v = yuv_cur->vstride; yuv_cur = yuv_cur->nextframe; jz47_put_image_with_ipu = jz47_put_image_with_direct_ipu_buffer; printf("create buf\n"); } printf("stride.y = %d\n",stride.y); printf("stride.u = %d\n",stride.u); printf("stride.v = %d\n",stride.v); printf("display_mode = %x\n",display_mode); lcd_ioctl(&img_param, IOCTL_DMA1_TO_IPU); }
int mpi_sub(MPI w, MPI u, MPI v) { int rc; if (w == v) { MPI vv; if (mpi_copy(&vv, v) < 0) return -ENOMEM; vv->sign = !vv->sign; rc = mpi_add(w, u, vv); mpi_free(vv); } else { v->sign = !v->sign; rc = mpi_add(w, u, v); v->sign = !v->sign; } return rc; }
void _gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ) { int divisor_sign = divisor->sign; gcry_mpi_t temp_divisor = NULL; if( quot == divisor || rem == divisor ) { temp_divisor = mpi_copy( divisor ); divisor = temp_divisor; } _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor ); if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { gcry_mpi_sub_ui( quot, quot, 1 ); gcry_mpi_add( rem, rem, divisor); } if( temp_divisor ) mpi_free(temp_divisor); }
static void sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey ) { gcry_mpi_t k; gcry_mpi_t t = mpi_alloc( mpi_get_nlimbs(a) ); gcry_mpi_t inv = mpi_alloc( mpi_get_nlimbs(a) ); gcry_mpi_t p_1 = mpi_copy(skey->p); /* * b = (t * inv) mod (p-1) * b = (t * inv(k,(p-1),(p-1)) mod (p-1) * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) * */ mpi_sub_ui(p_1, p_1, 1); k = gen_k( skey->p, 0 /* no small K ! */ ); gcry_mpi_powm( a, skey->g, k, skey->p ); mpi_mul(t, skey->x, a ); mpi_subm(t, input, t, p_1 ); mpi_invm(inv, k, p_1 ); mpi_mulm(b, t, inv, p_1 ); #if 0 if( DBG_CIPHER ) { log_mpidump("elg sign p= ", skey->p); log_mpidump("elg sign g= ", skey->g); log_mpidump("elg sign y= ", skey->y); log_mpidump("elg sign x= ", skey->x); log_mpidump("elg sign k= ", k); log_mpidump("elg sign M= ", input); log_mpidump("elg sign a= ", a); log_mpidump("elg sign b= ", b); } #endif mpi_free(k); mpi_free(t); mpi_free(inv); mpi_free(p_1); }
void _gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ) { int divisor_sign = divisor->sign; gcry_mpi_t temp_divisor = NULL; /* We need the original value of the divisor after the remainder has been * preliminary calculated. We have to copy it to temporary space if it's * the same variable as REM. */ if( rem == divisor ) { temp_divisor = mpi_copy( divisor ); divisor = temp_divisor; } _gcry_mpi_tdiv_r( rem, dividend, divisor ); if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) gcry_mpi_add( rem, rem, divisor); if( temp_divisor ) mpi_free(temp_divisor); }
/* * Get parameters from a keypair */ int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key, ecdh_side side ) { int ret; if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) return( ret ); /* If it's not our key, just import the public part as Qp */ if( side == POLARSSL_ECDH_THEIRS ) return( ecp_copy( &ctx->Qp, &key->Q ) ); /* Our key: import public (as Q) and private parts */ if( side != POLARSSL_ECDH_OURS ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); if( ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 || ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 ) return( ret ); return( 0 ); }
int jz47_put_image_with_direct_ipu_buffer (struct vf_instance_s* vf, mp_image_t *mpi, double pts) { #ifdef VERIFY_CRC32 SwsContext *c = vf->priv->ctx; crc32_verify (mpi->planes[0], c->srcH, c->srcW, mpi->stride[0]); crc32_verify (mpi->planes[1], c->srcH / 2, c->srcW / 2, mpi->stride[1]); crc32_verify (mpi->planes[2], c->srcH / 2, c->srcW / 2, mpi->stride[2]); #endif #if USE_OSD if(pFunction) pFunction(NULL); #endif if(yuv_next) { mpi_copy(yuv_next,mpi); yuv_next = yuv_next->nextframe; } if(yuv_cur) { // set Y(mpi->planes[0]), U(mpi->planes[1]), V addr (mpi->planes[2]) img_param.y_buf = yuv_cur->y_framebuf; // set U addr register (mpi->planes[1]) img_param.u_buf = yuv_cur->u_framebuf; // set V addr register (mpi->planes[2]) img_param.v_buf = yuv_cur->v_framebuf; // set Y(mpi->stride[0]) U(mpi->stride[1]) V(mpi->stride[2]) stride stride.y = yuv_cur->ystride; stride.u = yuv_cur->ustride; stride.v = yuv_cur->vstride; yuv_cur = yuv_cur->nextframe; lcd_flush_frame_all(); ipu_ioctl((void *)0, IOCTL_IPU_CHANGE_BUFF); } return 1; }
int main (int argc, char **argv) { const char *pgm; int last_argc = -1; int print_config = 0; int i, c; int state = 0; char strbuf[4096]; int stridx = 0; if (argc) { pgm = strrchr (*argv, '/'); if (pgm) pgm++; else pgm = *argv; argc--; argv++; } else pgm = "?"; while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--version") || !strcmp (*argv, "--help")) { printf ("%s " MPICALC_VERSION "\n" "libgcrypt %s\n" "Copyright (C) 1997, 2013 Werner Koch\n" "License LGPLv2.1+: GNU LGPL version 2.1 or later " "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n" "This is free software: you are free to change and " "redistribute it.\n" "There is NO WARRANTY, to the extent permitted by law.\n" "\n" "Syntax: mpicalc [options]\n" "Simple interactive big integer RPN calculator\n" "\n" "Options:\n" " --version print version information\n" " --print-config print the Libgcrypt config\n" " --disable-hwf NAME disable feature NAME\n", pgm, gcry_check_version (NULL)); exit (0); } else if (!strcmp (*argv, "--print-config")) { argc--; argv++; print_config = 1; } else if (!strcmp (*argv, "--disable-hwf")) { argc--; argv++; if (argc) { if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL)) fprintf (stderr, "%s: unknown hardware feature `%s'" " - option ignored\n", pgm, *argv); argc--; argv++; } } } if (argc) { fprintf (stderr, "usage: %s [options] (--help for help)\n", pgm); exit (1); } if (!gcry_check_version (NEED_LIBGCRYPT_VERSION)) { fprintf (stderr, "%s: Libgcrypt is too old (need %s, have %s)\n", pgm, NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); exit (1); } gcry_control (GCRYCTL_DISABLE_SECMEM, 0); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (print_config) { gcry_control (GCRYCTL_PRINT_CONFIG, stdout); exit (0); } for (i = 0; i < STACKSIZE; i++) stack[i] = NULL; stackidx = 0; while ((c = my_getc ()) != EOF) { if (!state) /* waiting */ { if (isdigit (c)) { state = 1; ungetc (c, stdin); strbuf[0] = '0'; strbuf[1] = 'x'; stridx = 2; } else if (isspace (c)) ; else { switch (c) { case '#': state = 2; break; case '+': if ((c = my_getc ()) == '+') do_inc (); else { ungetc (c, stdin); do_add (); } break; case '-': if ((c = my_getc ()) == '-') do_dec (); else if (isdigit (c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { state = 1; ungetc (c, stdin); strbuf[0] = '-'; strbuf[1] = '0'; strbuf[2] = 'x'; stridx = 3; } else { ungetc (c, stdin); do_sub (); } break; case '*': do_mul (); break; case 'm': do_mulm (); break; case '/': do_div (); break; case '%': do_rem (); break; case '^': do_powm (); break; case '<': do_lshift (); break; case '>': do_rshift (); break; case 'I': do_inv (); break; case 'G': do_gcd (); break; case 'i': /* dummy */ if (!stackidx) fputs ("stack underflow\n", stderr); else { mpi_release (stack[stackidx - 1]); stackidx--; } break; case 'd': /* duplicate the tos */ if (!stackidx) fputs ("stack underflow\n", stderr); else if (stackidx < STACKSIZE) { mpi_release (stack[stackidx]); stack[stackidx] = mpi_copy (stack[stackidx - 1]); stackidx++; } else fputs ("stack overflow\n", stderr); break; case 'r': /* swap top elements */ if (stackidx < 2) fputs ("stack underflow\n", stderr); else if (stackidx < STACKSIZE) { gcry_mpi_t tmp = stack[stackidx-1]; stack[stackidx-1] = stack[stackidx - 2]; stack[stackidx-2] = tmp; } break; case 'b': do_nbits (); break; case 'P': do_primecheck (); break; case 'c': for (i = 0; i < stackidx; i++) { mpi_release (stack[i]); stack[i] = NULL; } stackidx = 0; break; case 'p': /* print the tos */ if (!stackidx) puts ("stack is empty"); else { print_mpi (stack[stackidx - 1]); putchar ('\n'); } break; case 'f': /* print the stack */ for (i = stackidx - 1; i >= 0; i--) { printf ("[%2d]: ", i); print_mpi (stack[i]); putchar ('\n'); } break; case '?': print_help (); break; default: fputs ("invalid operator\n", stderr); } } } else if (state == 1) /* In a number. */ { if (!isxdigit (c)) { /* Store the number */ state = 0; ungetc (c, stdin); if (stridx < sizeof strbuf) strbuf[stridx] = 0; if (stackidx < STACKSIZE) { if (!stack[stackidx]) stack[stackidx] = mpi_new (0); if (scan_mpi (stack[stackidx], strbuf)) fputs ("invalid number\n", stderr); else stackidx++; } else fputs ("stack overflow\n", stderr); } else { /* Store a digit. */ if (stridx < sizeof strbuf - 1) strbuf[stridx++] = c; else if (stridx == sizeof strbuf - 1) { strbuf[stridx] = 0; fputs ("input too large - truncated\n", stderr); stridx++; } } } else if (state == 2) /* In a comment. */ { if (c == '\n') state = 0; } } for (i = 0; i < stackidx; i++) mpi_release (stack[i]); return 0; }
/**************** * We do not need to use the strongest RNG because we gain no extra * security from it - The prime number is public and we could also * offer the factors for those who are willing to check that it is * indeed a strong prime. With ALL_FACTORS set to true all afcors of * prime-1 are returned in FACTORS. * * mode 0: Standard * 1: Make sure that at least one factor is of size qbits. */ static gcry_err_code_t prime_generate_internal (int mode, gcry_mpi_t *prime_generated, unsigned int pbits, unsigned int qbits, gcry_mpi_t g, gcry_mpi_t **ret_factors, gcry_random_level_t randomlevel, unsigned int flags, int all_factors, gcry_prime_check_func_t cb_func, void *cb_arg) { gcry_err_code_t err = 0; gcry_mpi_t *factors_new = NULL; /* Factors to return to the caller. */ gcry_mpi_t *factors = NULL; /* Current factors. */ gcry_mpi_t *pool = NULL; /* Pool of primes. */ unsigned char *perms = NULL; /* Permutations of POOL. */ gcry_mpi_t q_factor = NULL; /* Used if QBITS is non-zero. */ unsigned int fbits = 0; /* Length of prime factors. */ unsigned int n = 0; /* Number of factors. */ unsigned int m = 0; /* Number of primes in pool. */ gcry_mpi_t q = NULL; /* First prime factor. */ gcry_mpi_t prime = NULL; /* Prime candidate. */ unsigned int nprime = 0; /* Bits of PRIME. */ unsigned int req_qbits; /* The original QBITS value. */ gcry_mpi_t val_2; /* For check_prime(). */ unsigned int is_secret = (flags & GCRY_PRIME_FLAG_SECRET); unsigned int count1 = 0, count2 = 0; unsigned int i = 0, j = 0; if (pbits < 48) return GPG_ERR_INV_ARG; /* If QBITS is not given, assume a reasonable value. */ if (!qbits) qbits = pbits / 3; req_qbits = qbits; /* Find number of needed prime factors. */ for (n = 1; (pbits - qbits - 1) / n >= qbits; n++) ; n--; val_2 = mpi_alloc_set_ui (2); if ((! n) || ((mode == 1) && (n < 2))) { err = GPG_ERR_INV_ARG; goto leave; } if (mode == 1) { n--; fbits = (pbits - 2 * req_qbits -1) / n; qbits = pbits - req_qbits - n * fbits; } else { fbits = (pbits - req_qbits -1) / n; qbits = pbits - n * fbits; } if (DBG_CIPHER) log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n); prime = gcry_mpi_new (pbits); /* Generate first prime factor. */ q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL); if (mode == 1) q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL); /* Allocate an array to hold the factors + 2 for later usage. */ factors = gcry_calloc (n + 2, sizeof (*factors)); if (!factors) { err = gpg_err_code_from_errno (errno); goto leave; } /* Make a pool of 3n+5 primes (this is an arbitrary value). */ m = n * 3 + 5; if (mode == 1) /* Need some more (for e.g. DSA). */ m += 5; if (m < 25) m = 25; pool = gcry_calloc (m , sizeof (*pool)); if (! pool) { err = gpg_err_code_from_errno (errno); goto leave; } /* Permutate over the pool of primes. */ do { next_try: if (! perms) { /* Allocate new primes. */ for(i = 0; i < m; i++) { mpi_free (pool[i]); pool[i] = NULL; } /* Init m_out_of_n(). */ perms = gcry_calloc (1, m); if (! perms) { err = gpg_err_code_from_errno (errno); goto leave; } for(i = 0; i < n; i++) { perms[i] = 1; pool[i] = gen_prime (fbits, is_secret, randomlevel, NULL, NULL); factors[i] = pool[i]; } } else { m_out_of_n ((char*)perms, n, m); for (i = j = 0; (i < m) && (j < n); i++) if (perms[i]) { if(! pool[i]) pool[i] = gen_prime (fbits, 0, 1, NULL, NULL); factors[j++] = pool[i]; } if (i == n) { gcry_free (perms); perms = NULL; progress ('!'); goto next_try; /* Allocate new primes. */ } } /* Generate next prime candidate: p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. */ mpi_set (prime, q); mpi_mul_ui (prime, prime, 2); if (mode == 1) mpi_mul (prime, prime, q_factor); for(i = 0; i < n; i++) mpi_mul (prime, prime, factors[i]); mpi_add_ui (prime, prime, 1); nprime = mpi_get_nbits (prime); if (nprime < pbits) { if (++count1 > 20) { count1 = 0; qbits++; progress('>'); mpi_free (q); q = gen_prime (qbits, 0, 0, NULL, NULL); goto next_try; } } else count1 = 0; if (nprime > pbits) { if (++count2 > 20) { count2 = 0; qbits--; progress('<'); mpi_free (q); q = gen_prime (qbits, 0, 0, NULL, NULL); goto next_try; } } else count2 = 0; } while (! ((nprime == pbits) && check_prime (prime, val_2, cb_func, cb_arg))); if (DBG_CIPHER) { progress ('\n'); log_mpidump ("prime : ", prime); log_mpidump ("factor q: ", q); if (mode == 1) log_mpidump ("factor q0: ", q_factor); for (i = 0; i < n; i++) log_mpidump ("factor pi: ", factors[i]); log_debug ("bit sizes: prime=%u, q=%u", mpi_get_nbits (prime), mpi_get_nbits (q)); if (mode == 1) log_debug (", q0=%u", mpi_get_nbits (q_factor)); for (i = 0; i < n; i++) log_debug (", p%d=%u", i, mpi_get_nbits (factors[i])); progress('\n'); } if (ret_factors) { /* Caller wants the factors. */ factors_new = gcry_calloc (n + 4, sizeof (*factors_new)); if (! factors_new) { err = gpg_err_code_from_errno (errno); goto leave; } if (all_factors) { i = 0; factors_new[i++] = gcry_mpi_set_ui (NULL, 2); factors_new[i++] = mpi_copy (q); if (mode == 1) factors_new[i++] = mpi_copy (q_factor); for(j=0; j < n; j++) factors_new[i++] = mpi_copy (factors[j]); } else { i = 0; if (mode == 1) { factors_new[i++] = mpi_copy (q_factor); for (; i <= n; i++) factors_new[i] = mpi_copy (factors[i]); } else for (; i < n; i++ ) factors_new[i] = mpi_copy (factors[i]); } } if (g) { /* Create a generator (start with 3). */ gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime)); if (mode == 1) err = GPG_ERR_NOT_IMPLEMENTED; else { factors[n] = q; factors[n + 1] = mpi_alloc_set_ui (2); mpi_sub_ui (pmin1, prime, 1); mpi_set_ui (g, 2); do { mpi_add_ui (g, g, 1); if (DBG_CIPHER) { log_debug ("checking g:"); gcry_mpi_dump (g); log_printf ("\n"); } else progress('^'); for (i = 0; i < n + 2; i++) { mpi_fdiv_q (tmp, pmin1, factors[i]); /* No mpi_pow(), but it is okay to use this with mod prime. */ gcry_mpi_powm (b, g, tmp, prime); if (! mpi_cmp_ui (b, 1)) break; } if (DBG_CIPHER) progress('\n'); } while (i < n + 2); mpi_free (factors[n+1]); mpi_free (tmp); mpi_free (b); mpi_free (pmin1); } } if (! DBG_CIPHER) progress ('\n'); leave: if (pool) { for(i = 0; i < m; i++) mpi_free (pool[i]); gcry_free (pool); } if (factors) gcry_free (factors); /* Factors are shallow copies. */ if (perms) gcry_free (perms); mpi_free (val_2); mpi_free (q); mpi_free (q_factor); if (! err) { *prime_generated = prime; if (ret_factors) *ret_factors = factors_new; } else { if (factors_new) { for (i = 0; factors_new[i]; i++) mpi_free (factors_new[i]); gcry_free (factors_new); } mpi_free (prime); } return err; }
/**************** * Generate a random secret exponent k from prime p, so that k is * relatively prime to p-1. With SMALL_K set, k will be selected for * better encryption performance - this must never be used signing! */ static gcry_mpi_t gen_k( gcry_mpi_t p, int small_k ) { gcry_mpi_t k = mpi_alloc_secure( 0 ); gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) ); gcry_mpi_t p_1 = mpi_copy(p); unsigned int orig_nbits = mpi_get_nbits(p); unsigned int nbits, nbytes; char *rndbuf = NULL; if (small_k) { /* Using a k much lesser than p is sufficient for encryption and * it greatly improves the encryption performance. We use * Wiener's table and add a large safety margin. */ nbits = wiener_map( orig_nbits ) * 3 / 2; if( nbits >= orig_nbits ) BUG(); } else nbits = orig_nbits; nbytes = (nbits+7)/8; if( DBG_CIPHER ) log_debug("choosing a random k "); mpi_sub_ui( p_1, p, 1); for(;;) { if( !rndbuf || nbits < 32 ) { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM ); } else { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call to get_random_bytes() and use this the here maybe it is easier to do this directly in random.c Anyway, it is highly inlikely that we will ever reach this code. */ char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); memcpy( rndbuf, pp, 4 ); gcry_free(pp); } _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); for(;;) { if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */ { if( DBG_CIPHER ) progress('+'); break; /* no */ } if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */ { if( DBG_CIPHER ) progress('-'); break; /* no */ } if (gcry_mpi_gcd( temp, k, p_1 )) goto found; /* okay, k is relative prime to (p-1) */ mpi_add_ui( k, k, 1 ); if( DBG_CIPHER ) progress('.'); } } found: gcry_free(rndbuf); if( DBG_CIPHER ) progress('\n'); mpi_free(p_1); mpi_free(temp); return k; }
/**************** * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M */ int mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) { int rc = -ENOMEM; int k; /* number of elements */ int t; /* bit size of largest exponent */ int i, j, idx; MPI *G = NULL; /* table with precomputed values of size 2^k */ MPI tmp = NULL; for(k=0; basearray[k]; k++ ) ; if (!k) { printk("mpi_mulpowm: assert(k) failed\n"); BUG(); } for(t=0, i=0; (tmp=exparray[i]); i++ ) { j = mpi_get_nbits(tmp); if( j > t ) t = j; } if (i!=k) { printk("mpi_mulpowm: assert(i==k) failed\n"); BUG(); } if (!t) { printk("mpi_mulpowm: assert(t) failed\n"); BUG(); } if (k>=10) { printk("mpi_mulpowm: assert(k<10) failed\n"); BUG(); } //daveti: hack //G = kzalloc( (1<<k) * sizeof *G, GFP_KERNEL ); G = kzalloc( (1<<k) * sizeof *G, GFP_ATOMIC ); if (!G) goto nomem; /* and calculate */ tmp = mpi_alloc( mpi_get_nlimbs(m)+1 ); if (!tmp) goto nomem; if (mpi_set_ui( res, 1 ) < 0) goto nomem; for(i = 1; i <= t; i++ ) { if (mpi_mulm(tmp, res, res, m ) < 0) goto nomem; idx = build_index( exparray, k, i, t ); if (!(idx >= 0 && idx < (1<<k))) { printk("mpi_mulpowm: assert(idx >= 0 && idx < (1<<k)) failed\n"); BUG(); } if( !G[idx] ) { if( !idx ) { G[0] = mpi_alloc_set_ui( 1 ); if (!G[0]) goto nomem; } else { for(j=0; j < k; j++ ) { if( (idx & (1<<j) ) ) { if( !G[idx] ) { if (mpi_copy( &G[idx], basearray[j] ) < 0) goto nomem; } else { if (mpi_mulm(G[idx],G[idx],basearray[j],m) < 0) goto nomem; } } } if( !G[idx] ) { G[idx] = mpi_alloc(0); if (!G[idx]) goto nomem; } } } if (mpi_mulm(res, tmp, G[idx], m ) < 0) goto nomem; } rc = 0; nomem: /* cleanup */ mpi_free(tmp); for(i=0; i < (1<<k); i++ ) mpi_free(G[i]); kfree(G); return rc; }
/* Scalar point multiplication - the main function for ECC. If takes an integer SCALAR and a POINT as well as the usual context CTX. RESULT will be set to the resulting point. */ void _gcry_mpi_ec_mul_point (mpi_point_t result, gcry_mpi_t scalar, mpi_point_t point, mpi_ec_t ctx) { #if 0 /* Simple left to right binary method. GECC Algorithm 3.27 */ unsigned int nbits; int i; nbits = mpi_get_nbits (scalar); mpi_set_ui (result->x, 1); mpi_set_ui (result->y, 1); mpi_set_ui (result->z, 0); for (i=nbits-1; i >= 0; i--) { _gcry_mpi_ec_dup_point (result, result, ctx); if (mpi_test_bit (scalar, i) == 1) _gcry_mpi_ec_add_points (result, result, point, ctx); } #else gcry_mpi_t x1, y1, z1, k, h, yy; unsigned int i, loops; mpi_point_struct p1, p2, p1inv; x1 = mpi_alloc_like (ctx->p); y1 = mpi_alloc_like (ctx->p); h = mpi_alloc_like (ctx->p); k = mpi_copy (scalar); yy = mpi_copy (point->y); if ( mpi_is_neg (k) ) { k->sign = 0; ec_invm (yy, yy, ctx); } if (!mpi_cmp_ui (point->z, 1)) { mpi_set (x1, point->x); mpi_set (y1, yy); } else { gcry_mpi_t z2, z3; z2 = mpi_alloc_like (ctx->p); z3 = mpi_alloc_like (ctx->p); ec_mulm (z2, point->z, point->z, ctx); ec_mulm (z3, point->z, z2, ctx); ec_invm (z2, z2, ctx); ec_mulm (x1, point->x, z2, ctx); ec_invm (z3, z3, ctx); ec_mulm (y1, yy, z3, ctx); mpi_free (z2); mpi_free (z3); } z1 = mpi_copy (mpi_const (MPI_C_ONE)); mpi_mul (h, k, mpi_const (MPI_C_THREE)); /* h = 3k */ loops = mpi_get_nbits (h); if (loops < 2) { /* If SCALAR is zero, the above mpi_mul sets H to zero and thus LOOPs will be zero. To avoid an underflow of I in the main loop we set LOOP to 2 and the result to (0,0,0). */ loops = 2; mpi_clear (result->x); mpi_clear (result->y); mpi_clear (result->z); } else { mpi_set (result->x, point->x); mpi_set (result->y, yy); mpi_set (result->z, point->z); } mpi_free (yy); yy = NULL; p1.x = x1; x1 = NULL; p1.y = y1; y1 = NULL; p1.z = z1; z1 = NULL; point_init (&p2); point_init (&p1inv); for (i=loops-2; i > 0; i--) { _gcry_mpi_ec_dup_point (result, result, ctx); if (mpi_test_bit (h, i) == 1 && mpi_test_bit (k, i) == 0) { point_set (&p2, result); _gcry_mpi_ec_add_points (result, &p2, &p1, ctx); } if (mpi_test_bit (h, i) == 0 && mpi_test_bit (k, i) == 1) { point_set (&p2, result); /* Invert point: y = p - y mod p */ point_set (&p1inv, &p1); ec_subm (p1inv.y, ctx->p, p1inv.y, ctx); _gcry_mpi_ec_add_points (result, &p2, &p1inv, ctx); } } point_free (&p1); point_free (&p2); point_free (&p1inv); mpi_free (h); mpi_free (k); #endif }
/* * Return true if n is probably a prime */ static int is_prime (gcry_mpi_t n, int steps, unsigned int *count) { gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t z = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t nminus1 = mpi_alloc( mpi_get_nlimbs( n ) ); gcry_mpi_t a2 = mpi_alloc_set_ui( 2 ); gcry_mpi_t q; unsigned i, j, k; int rc = 0; unsigned nbits = mpi_get_nbits( n ); mpi_sub_ui( nminus1, n, 1 ); /* Find q and k, so that n = 1 + 2^k * q . */ q = mpi_copy ( nminus1 ); k = mpi_trailing_zeros ( q ); mpi_tdiv_q_2exp (q, q, k); for (i=0 ; i < steps; i++ ) { ++*count; if( !i ) { mpi_set_ui( x, 2 ); } else { gcry_mpi_randomize( x, nbits, GCRY_WEAK_RANDOM ); /* Make sure that the number is smaller than the prime and keep the randomness of the high bit. */ if ( mpi_test_bit ( x, nbits-2) ) { mpi_set_highbit ( x, nbits-2); /* Clear all higher bits. */ } else { mpi_set_highbit( x, nbits-2 ); mpi_clear_bit( x, nbits-2 ); } assert ( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 ); } gcry_mpi_powm ( y, x, q, n); if ( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) { for ( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) { gcry_mpi_powm(y, y, a2, n); if( !mpi_cmp_ui( y, 1 ) ) goto leave; /* Not a prime. */ } if (mpi_cmp( y, nminus1 ) ) goto leave; /* Not a prime. */ } progress('+'); } rc = 1; /* May be a prime. */ leave: mpi_free( x ); mpi_free( y ); mpi_free( z ); mpi_free( nminus1 ); mpi_free( q ); mpi_free( a2 ); return rc; }