void CoreAudioPaddedEncoder::extrapolate0() { unsigned nchannels = getInputDescription().mChannelsPerFrame; unsigned bpf = getInputDescription().mBytesPerFrame; unsigned shift = (getOutputDescription().mFormatID == 'aach') ? 1 : 0; unsigned fpp = getOutputDescription().mFramesPerPacket; unsigned nsamples = fpp / 2; unsigned padding = (getOutputDescription().mFormatID == 'aac ') ? m_num_priming + 3 * fpp - APPLE_NUM_PRIMING - nsamples : nsamples; std::vector<float> buf(nsamples * nchannels); size_t n = readSamplesFull(src(), &buf[0], nsamples); m_buffer.reserve(nsamples + n + padding); if (padding > 0) { std::memset(m_buffer.write_ptr(), 0, padding * bpf); m_buffer.commit(padding); } if (n < 2 * LPC_ORDER) std::memset(m_buffer.write_ptr(), 0, nsamples * bpf); else { reverse_buffer(&buf[0], n, nchannels); extrapolate(&buf[0], n, m_buffer.write_ptr(), nsamples); reverse_buffer(m_buffer.write_ptr(), nsamples, nchannels); reverse_buffer(&buf[0], n, nchannels); } m_buffer.commit(nsamples); std::copy(buf.begin(), buf.begin() + n * nchannels, m_buffer.write_ptr()); m_buffer.commit(n); }
void decrunch_backwards(int level, struct membuf *inbuf, struct membuf *outbuf) { int outpos; reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf)); outpos = membuf_memlen(outbuf); decrunch(level, inbuf, outbuf); reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf)); reverse_buffer((char*)membuf_get(outbuf) + outpos, membuf_memlen(outbuf) - outpos); }
void crunch(struct membuf *inbuf, struct membuf *outbuf, struct crunch_options *options, /* IN */ struct crunch_info *info) /* OUT */ { int outpos; reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf)); outpos = membuf_memlen(outbuf); crunch_backwards(inbuf, outbuf, options, info); reverse_buffer(membuf_get(inbuf), membuf_memlen(inbuf)); reverse_buffer((char*)membuf_get(outbuf) + outpos, membuf_memlen(outbuf) - outpos); }
static int process0(extrapolater_t *self, void *buffer, unsigned nframes) { const pcm_sample_description_t *sfmt = pcm_get_format(self->src); unsigned nchannels = sfmt->channels_per_frame; buffer_t *bp = &self->buffer[self->nbuffer]; if (fetch(self, nframes) < 2 * LPC_ORDER) memset(buffer, 0, nframes * sfmt->bytes_per_frame); else { reverse_buffer(bp->data, bp->count, nchannels); extrapolate(self, bp, buffer, nframes); reverse_buffer(buffer, nframes, nchannels); reverse_buffer(bp->data, bp->count, nchannels); } self->process = bp->count ? process1 : process2; return nframes; }
/* Compute the A value as used by EdDSA. The caller needs to provide the context EC and the actual secret D as an MPI. The function returns a newly allocated 64 byte buffer at r_digest; the first 32 bytes represent the A value. NULL is returned on error and NULL stored at R_DIGEST. */ gpg_err_code_t _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest, gcry_mpi_t d, mpi_ec_t ec) { gpg_err_code_t rc; unsigned char *rawmpi = NULL; unsigned int rawmpilen; unsigned char *digest; gcry_buffer_t hvec[2]; int hashalgo, b; *r_digest = NULL; hashalgo = GCRY_MD_SHA512; if (hashalgo != GCRY_MD_SHA512) return GPG_ERR_DIGEST_ALGO; b = (ec->nbits+7)/8; if (b != 256/8) return GPG_ERR_INTERNAL; /* We only support 256 bit. */ /* Note that we clear DIGEST so we can use it as input to left pad the key with zeroes for hashing. */ digest = xtrycalloc_secure (2, b); if (!digest) return gpg_err_code_from_syserror (); memset (hvec, 0, sizeof hvec); rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL); if (!rawmpi) { xfree (digest); return gpg_err_code_from_syserror (); } hvec[0].data = digest; hvec[0].off = 0; hvec[0].len = b > rawmpilen? b - rawmpilen : 0; hvec[1].data = rawmpi; hvec[1].off = 0; hvec[1].len = rawmpilen; rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2); xfree (rawmpi); if (rc) { xfree (digest); return rc; } /* Compute the A value. */ reverse_buffer (digest, 32); /* Only the first half of the hash. */ digest[0] = (digest[0] & 0x7f) | 0x40; digest[31] &= 0xf8; *r_digest = digest; return 0; }
static void fill_response_params(TEE_Param *params) { uint32_t i; /* Param 0 */ params[0].value.a = OUT_VALUE_A; params[0].value.b = OUT_VALUE_B; /* Param 1 & 2 */ for (i = 1; i < 3; i++) { TEE_MemMove(params[i].memref.buffer, out_vector, SIZE_OF_VEC(out_vector)); params[i].memref.size = SIZE_OF_VEC(out_vector); } /* Param 3 */ reverse_buffer(params[3].memref.buffer, params[3].memref.size, ¶ms[3].memref.size); }
static void level(const char *appl, int argc, char *argv[]) { char flags_arr[32]; int forward_mode = 0; int literal_sequences_used = 0; int max_safety = 0; int c; int infilec; char **infilev; struct crunch_options options[1] = { CRUNCH_OPTIONS_DEFAULT }; struct common_flags flags[1] = {{NULL, DEFAULT_OUTFILE}}; struct membuf in[1]; struct membuf out[1]; flags->options = options; LOG(LOG_DUMP, ("flagind %d\n", flagind)); sprintf(flags_arr, "f%s", CRUNCH_FLAGS); while ((c = getflag(argc, argv, flags_arr)) != -1) { LOG(LOG_DUMP, (" flagind %d flagopt '%c'\n", flagind, c)); switch (c) { case 'f': forward_mode = 1; break; default: handle_crunch_flags(c, flagarg, print_level_usage, appl, flags); } } membuf_init(in); membuf_init(out); infilev = argv + flagind; infilec = argc - flagind; if (infilec == 0) { LOG(LOG_ERROR, ("Error: no input files to process.\n")); print_level_usage(appl, LOG_NORMAL, DEFAULT_OUTFILE); exit(1); } /* append the files instead of merging them */ for(c = 0; c < infilec; ++c) { struct crunch_info info[1]; int in_load; int in_len; int out_pos; out_pos = membuf_memlen(out); in_load = do_load(infilev[c], in); in_len = membuf_memlen(in); if(forward_mode) { /* append the starting address of decrunching */ membuf_append_char(out, in_load >> 8); membuf_append_char(out, in_load & 255); crunch(in, out, options, info); } else { crunch_backwards(in, out, options, info); /* append the starting address of decrunching */ membuf_append_char(out, (in_load + in_len) & 255); membuf_append_char(out, (in_load + in_len) >> 8); /* reverse the just appended segment of the out buffer */ reverse_buffer((char*)membuf_get(out) + out_pos, membuf_memlen(out) - out_pos); } if(info->literal_sequences_used) { literal_sequences_used = 1; } if(info->needed_safety_offset > max_safety) { max_safety = info->needed_safety_offset; } }
int icv_rot(size_t argc, const char *argv[]) { const size_t MAXPIXELS = 16768 * 16768; /* boo hiss */ ssize_t x, y; size_t j; int ret = 0; off_t outbyte, outplace; FILE *ifp, *ofp; unsigned char *obuf; unsigned char *buffer; double angle = 0.0; ssize_t wrote = 0; ifp = stdin; ofp = stdout; bu_setprogname(argv[0]); if (!get_args(argc, argv, &ifp, &ofp, &angle)) { bu_exit(1, "Usage: %s [-rifb | -a angle] [-# bytes] [-s squaresize] [-w width] [-n height] [-o outputfile] inputfile [> outputfile]\n", argv[0]); } scanbytes = nxin * pixbytes; buflines = MAXPIXELS / nxin; if (buflines <= 0) { bu_exit(1, "ERROR: %s is not compiled to handle a scanline that long!\n", argv[0]); } if (buflines > nyin) buflines = nyin; buffer = (unsigned char *)bu_malloc(buflines * scanbytes, "buffer"); obuf = (unsigned char *)bu_malloc((nyin > nxin) ? nyin*pixbytes : nxin*pixbytes, "obuf"); /* * Break out to added arbitrary angle routine */ if (angle > 0.0) { arbrot(angle, ifp, buffer); goto done; } /* * Clear our "file pointer." We need to maintain this * In order to tell if seeking is required. ftell() always * fails on pipes, so we can't use it. */ outplace = 0; yin = 0; while (yin < nyin) { /* Fill buffer */ fill_buffer(ifp, buffer); if (!buflines) break; if (reverse) reverse_buffer(buffer); if (plus90) { for (x = 0; x < nxin; x++) { obp = obuf; bp = &buffer[ (lasty-firsty)*scanbytes + x*pixbytes ]; for (y = lasty+1; y > yin; y--) { /* firsty? */ for (j = 0; j < pixbytes; j++) *obp++ = *bp++; bp -= scanbytes + pixbytes; } yout = x; xout = (nyin - 1) - lasty; outbyte = ((yout * nyin) + xout) * pixbytes; if (outplace != outbyte) { if (bu_fseek(ofp, outbyte, SEEK_SET) < 0) { ret = 3; perror("fseek"); bu_log("ERROR: %s can't seek on output (ofp=%p, outbyte=%zd)\n", argv[0], (void *)ofp, outbyte); goto done; } outplace = outbyte; } wrote = fwrite(obuf, pixbytes, buflines, ofp); if (wrote != buflines) { ret = 4; perror("fwrite"); bu_log("ERROR: %s can't out write image data (wrote %zd of %zd)\n", argv[0], wrote, buflines); goto done; } outplace += buflines*pixbytes; } } else if (minus90) { for (x = nxin; x > 0; x--) { obp = obuf; bp = &buffer[ (x-1)*pixbytes ]; for (y = firsty+1; (ssize_t)y < lasty; y++) { for (j = 0; j < pixbytes; j++) *obp++ = *bp++; bp += scanbytes - pixbytes; } yout = (nxin - 1) - x + 1; xout = yin; outbyte = ((yout * nyin) + xout) * pixbytes; if (outplace != outbyte) { if (bu_fseek(ofp, outbyte, SEEK_SET) < 0) { ret = 3; perror("fseek"); bu_log("ERROR: %s can't seek on output (ofp=%p, outbyte=%zd)\n", argv[0], (void *)ofp, outbyte); goto done; } outplace = outbyte; } wrote = fwrite(obuf, pixbytes, buflines, ofp); if (wrote != buflines) { ret = 4; perror("fwrite"); bu_log("ERROR: %s can't out write image data (wrote %zd of %zd)\n", argv[0], wrote, buflines); goto done; } outplace += buflines*pixbytes; } } else if (invert) { for (y = lasty+1; (ssize_t)y > firsty; y--) { yout = (nyin - 1) - y + 1; outbyte = yout * scanbytes; if (outplace != outbyte) { if (bu_fseek(ofp, outbyte, SEEK_SET) < 0) { ret = 3; perror("fseek"); bu_log("ERROR: %s can't seek on output (ofp=%p, outbyte=%zd)\n", argv[0], (void *)ofp, outbyte); goto done; } outplace = outbyte; } wrote = fwrite(&buffer[(y-firsty-1)*scanbytes], 1, scanbytes, ofp); if (wrote != scanbytes) { ret = 4; perror("fwrite"); bu_log("ERROR: %s can't out write image data (wrote %zd of %zd)\n", argv[0], wrote, scanbytes); goto done; } outplace += scanbytes; } } else { /* Reverse only */ for (y = 0; y < buflines; y++) { wrote = fwrite(&buffer[y*scanbytes], 1, scanbytes, ofp); if (wrote != scanbytes) { ret = 4; perror("fwrite"); bu_log("ERROR: %s can't out write image data (wrote %zd of %zd)\n", argv[0], wrote, scanbytes); goto done; } } } yin += buflines; } done: fclose(ifp); bu_free(buffer, "buffer"); bu_free(obuf, "obuf"); return ret; }
/* Verify an EdDSA signature. See sign_eddsa for the reference. * Check if R_IN and S_IN verifies INPUT. PKEY has the curve * parameters and PK is the EdDSA style encoded public key. */ gpg_err_code_t _gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r_in, gcry_mpi_t s_in, int hashalgo, gcry_mpi_t pk) { int rc; mpi_ec_t ctx = NULL; int b; unsigned int tmp; mpi_point_struct Q; /* Public key. */ unsigned char *encpk = NULL; /* Encoded public key. */ unsigned int encpklen; const void *mbuf, *rbuf; unsigned char *tbuf = NULL; size_t mlen, rlen; unsigned int tlen; unsigned char digest[64]; gcry_buffer_t hvec[3]; gcry_mpi_t h, s; mpi_point_struct Ia, Ib; if (!mpi_is_opaque (input) || !mpi_is_opaque (r_in) || !mpi_is_opaque (s_in)) return GPG_ERR_INV_DATA; if (hashalgo != GCRY_MD_SHA512) return GPG_ERR_DIGEST_ALGO; point_init (&Q); point_init (&Ia); point_init (&Ib); h = mpi_new (0); s = mpi_new (0); ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0, pkey->E.p, pkey->E.a, pkey->E.b); b = ctx->nbits/8; if (b != 256/8) return GPG_ERR_INTERNAL; /* We only support 256 bit. */ /* Decode and check the public key. */ rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q, &encpk, &encpklen); if (rc) goto leave; if (!_gcry_mpi_ec_curve_point (&Q, ctx)) { rc = GPG_ERR_BROKEN_PUBKEY; goto leave; } if (DBG_CIPHER) log_printhex (" e_pk", encpk, encpklen); if (encpklen != b) { rc = GPG_ERR_INV_LENGTH; goto leave; } /* Convert the other input parameters. */ mbuf = mpi_get_opaque (input, &tmp); mlen = (tmp +7)/8; if (DBG_CIPHER) log_printhex (" m", mbuf, mlen); rbuf = mpi_get_opaque (r_in, &tmp); rlen = (tmp +7)/8; if (DBG_CIPHER) log_printhex (" r", rbuf, rlen); if (rlen != b) { rc = GPG_ERR_INV_LENGTH; goto leave; } /* h = H(encodepoint(R) + encodepoint(pk) + m) */ hvec[0].data = (char*)rbuf; hvec[0].off = 0; hvec[0].len = rlen; hvec[1].data = encpk; hvec[1].off = 0; hvec[1].len = encpklen; hvec[2].data = (char*)mbuf; hvec[2].off = 0; hvec[2].len = mlen; rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 3); if (rc) goto leave; reverse_buffer (digest, 64); if (DBG_CIPHER) log_printhex (" H(R+)", digest, 64); _gcry_mpi_set_buffer (h, digest, 64, 0); /* According to the paper the best way for verification is: encodepoint(sG - h·Q) = encodepoint(r) because we don't need to decode R. */ { void *sbuf; unsigned int slen; sbuf = _gcry_mpi_get_opaque_copy (s_in, &tmp); slen = (tmp +7)/8; reverse_buffer (sbuf, slen); if (DBG_CIPHER) log_printhex (" s", sbuf, slen); _gcry_mpi_set_buffer (s, sbuf, slen, 0); xfree (sbuf); if (slen != b) { rc = GPG_ERR_INV_LENGTH; goto leave; } } _gcry_mpi_ec_mul_point (&Ia, s, &pkey->E.G, ctx); _gcry_mpi_ec_mul_point (&Ib, h, &Q, ctx); _gcry_mpi_neg (Ib.x, Ib.x); _gcry_mpi_ec_add_points (&Ia, &Ia, &Ib, ctx); rc = _gcry_ecc_eddsa_encodepoint (&Ia, ctx, s, h, 0, &tbuf, &tlen); if (rc) goto leave; if (tlen != rlen || memcmp (tbuf, rbuf, tlen)) { rc = GPG_ERR_BAD_SIGNATURE; goto leave; } rc = 0; leave: xfree (encpk); xfree (tbuf); _gcry_mpi_ec_free (ctx); _gcry_mpi_release (s); _gcry_mpi_release (h); point_free (&Ia); point_free (&Ib); point_free (&Q); return rc; }
/* Compute an EdDSA signature. See: * [ed25519] 23pp. (PDF) Daniel J. Bernstein, Niels Duif, Tanja * Lange, Peter Schwabe, Bo-Yin Yang. High-speed high-security * signatures. Journal of Cryptographic Engineering 2 (2012), 77-89. * Document ID: a1a62a2f76d23f65d622484ddd09caf8. * URL: http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26. * * Despite that this function requires the specification of a hash * algorithm, we only support what has been specified by the paper. * This may change in the future. Note that we don't check the used * curve; the user is responsible to use Ed25519. * * Return the signature struct (r,s) from the message hash. The caller * must have allocated R_R and S. */ gpg_err_code_t _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r_r, gcry_mpi_t s, int hashalgo, gcry_mpi_t pk) { int rc; mpi_ec_t ctx = NULL; int b; unsigned int tmp; unsigned char *digest; gcry_buffer_t hvec[3]; const void *mbuf; size_t mlen; unsigned char *rawmpi = NULL; unsigned int rawmpilen; unsigned char *encpk = NULL; /* Encoded public key. */ unsigned int encpklen; mpi_point_struct I; /* Intermediate value. */ mpi_point_struct Q; /* Public key. */ gcry_mpi_t a, x, y, r; memset (hvec, 0, sizeof hvec); if (!mpi_is_opaque (input)) return GPG_ERR_INV_DATA; /* Initialize some helpers. */ point_init (&I); point_init (&Q); a = mpi_snew (0); x = mpi_new (0); y = mpi_new (0); r = mpi_new (0); ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0, skey->E.p, skey->E.a, skey->E.b); b = (ctx->nbits+7)/8; if (b != 256/8) return GPG_ERR_INTERNAL; /* We only support 256 bit. */ rc = _gcry_ecc_eddsa_compute_h_d (&digest, skey->d, ctx); if (rc) goto leave; _gcry_mpi_set_buffer (a, digest, 32, 0); /* Compute the public key if it has not been supplied as optional parameter. */ if (pk) { rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q, &encpk, &encpklen); if (rc) goto leave; if (DBG_CIPHER) log_printhex ("* e_pk", encpk, encpklen); if (!_gcry_mpi_ec_curve_point (&Q, ctx)) { rc = GPG_ERR_BROKEN_PUBKEY; goto leave; } } else { _gcry_mpi_ec_mul_point (&Q, a, &skey->E.G, ctx); rc = _gcry_ecc_eddsa_encodepoint (&Q, ctx, x, y, 0, &encpk, &encpklen); if (rc) goto leave; if (DBG_CIPHER) log_printhex (" e_pk", encpk, encpklen); } /* Compute R. */ mbuf = mpi_get_opaque (input, &tmp); mlen = (tmp +7)/8; if (DBG_CIPHER) log_printhex (" m", mbuf, mlen); hvec[0].data = digest; hvec[0].off = 32; hvec[0].len = 32; hvec[1].data = (char*)mbuf; hvec[1].len = mlen; rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2); if (rc) goto leave; reverse_buffer (digest, 64); if (DBG_CIPHER) log_printhex (" r", digest, 64); _gcry_mpi_set_buffer (r, digest, 64, 0); _gcry_mpi_ec_mul_point (&I, r, &skey->E.G, ctx); if (DBG_CIPHER) log_printpnt (" r", &I, ctx); /* Convert R into affine coordinates and apply encoding. */ rc = _gcry_ecc_eddsa_encodepoint (&I, ctx, x, y, 0, &rawmpi, &rawmpilen); if (rc) goto leave; if (DBG_CIPHER) log_printhex (" e_r", rawmpi, rawmpilen); /* S = r + a * H(encodepoint(R) + encodepoint(pk) + m) mod n */ hvec[0].data = rawmpi; /* (this is R) */ hvec[0].off = 0; hvec[0].len = rawmpilen; hvec[1].data = encpk; hvec[1].off = 0; hvec[1].len = encpklen; hvec[2].data = (char*)mbuf; hvec[2].off = 0; hvec[2].len = mlen; rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 3); if (rc) goto leave; /* No more need for RAWMPI thus we now transfer it to R_R. */ mpi_set_opaque (r_r, rawmpi, rawmpilen*8); rawmpi = NULL; reverse_buffer (digest, 64); if (DBG_CIPHER) log_printhex (" H(R+)", digest, 64); _gcry_mpi_set_buffer (s, digest, 64, 0); mpi_mulm (s, s, a, skey->E.n); mpi_addm (s, s, r, skey->E.n); rc = eddsa_encodempi (s, b, &rawmpi, &rawmpilen); if (rc) goto leave; if (DBG_CIPHER) log_printhex (" e_s", rawmpi, rawmpilen); mpi_set_opaque (s, rawmpi, rawmpilen*8); rawmpi = NULL; rc = 0; leave: _gcry_mpi_release (a); _gcry_mpi_release (x); _gcry_mpi_release (y); _gcry_mpi_release (r); xfree (digest); _gcry_mpi_ec_free (ctx); point_free (&I); point_free (&Q); xfree (encpk); xfree (rawmpi); return rc; }
/** * _gcry_ecc_eddsa_genkey - EdDSA version of the key generation. * * @sk: A struct to receive the secret key. * @E: Parameters of the curve. * @ctx: Elliptic curve computation context. * @flags: Flags controlling aspects of the creation. * * Return: An error code. * * The only @flags bit used by this function is %PUBKEY_FLAG_TRANSIENT * to use a faster RNG. */ gpg_err_code_t _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, int flags) { gpg_err_code_t rc; int b = 256/8; /* The only size we currently support. */ gcry_mpi_t a, x, y; mpi_point_struct Q; gcry_random_level_t random_level; char *dbuf; size_t dlen; gcry_buffer_t hvec[1]; unsigned char *hash_d = NULL; point_init (&Q); memset (hvec, 0, sizeof hvec); if ((flags & PUBKEY_FLAG_TRANSIENT_KEY)) random_level = GCRY_STRONG_RANDOM; else random_level = GCRY_VERY_STRONG_RANDOM; a = mpi_snew (0); x = mpi_new (0); y = mpi_new (0); /* Generate a secret. */ hash_d = xtrymalloc_secure (2*b); if (!hash_d) { rc = gpg_error_from_syserror (); goto leave; } dlen = b; dbuf = _gcry_random_bytes_secure (dlen, random_level); /* Compute the A value. */ hvec[0].data = dbuf; hvec[0].len = dlen; rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, hash_d, hvec, 1); if (rc) goto leave; sk->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8); dbuf = NULL; reverse_buffer (hash_d, 32); /* Only the first half of the hash. */ hash_d[0] = (hash_d[0] & 0x7f) | 0x40; hash_d[31] &= 0xf8; _gcry_mpi_set_buffer (a, hash_d, 32, 0); xfree (hash_d); hash_d = NULL; /* log_printmpi ("ecgen a", a); */ /* Compute Q. */ _gcry_mpi_ec_mul_point (&Q, a, &E->G, ctx); if (DBG_CIPHER) log_printpnt ("ecgen pk", &Q, ctx); /* Copy the stuff to the key structures. */ sk->E.model = E->model; sk->E.dialect = E->dialect; sk->E.p = mpi_copy (E->p); sk->E.a = mpi_copy (E->a); sk->E.b = mpi_copy (E->b); point_init (&sk->E.G); point_set (&sk->E.G, &E->G); sk->E.n = mpi_copy (E->n); point_init (&sk->Q); point_set (&sk->Q, &Q); leave: point_free (&Q); _gcry_mpi_release (a); _gcry_mpi_release (x); _gcry_mpi_release (y); xfree (hash_d); return rc; }
/* Decode the EdDSA style encoded PK and set it into RESULT. CTX is the usual curve context. If R_ENCPK is not NULL, the encoded PK is stored at that address; this is a new copy to be released by the caller. In contrast to the supplied PK, this is not an MPI and thus guaranteed to be properly padded. R_ENCPKLEN receives the length of that encoded key. */ gpg_err_code_t _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result, unsigned char **r_encpk, unsigned int *r_encpklen) { gpg_err_code_t rc; unsigned char *rawmpi; unsigned int rawmpilen; int sign; if (mpi_is_opaque (pk)) { const unsigned char *buf; buf = mpi_get_opaque (pk, &rawmpilen); if (!buf) return GPG_ERR_INV_OBJ; rawmpilen = (rawmpilen + 7)/8; /* Handle compression prefixes. The size of the buffer will be odd in this case. */ if (rawmpilen > 1 && (rawmpilen%2)) { /* First check whether the public key has been given in standard uncompressed format (SEC1). No need to recover x in this case. */ if (buf[0] == 0x04) { gcry_mpi_t x, y; rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD, buf+1, (rawmpilen-1)/2, NULL); if (rc) return rc; rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD, buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2,NULL); if (rc) { mpi_free (x); return rc; } if (r_encpk) { rc = eddsa_encode_x_y (x, y, ctx->nbits/8, 0, r_encpk, r_encpklen); if (rc) { mpi_free (x); mpi_free (y); return rc; } } mpi_snatch (result->x, x); mpi_snatch (result->y, y); mpi_set_ui (result->z, 1); return 0; } /* Check whether the public key has been prefixed with a 0x40 byte to explicitly indicate compressed format using a SEC1 alike prefix byte. This is a Libgcrypt extension. */ if (buf[0] == 0x40) { rawmpilen--; buf++; } } /* EdDSA compressed point. */ rawmpi = xtrymalloc (rawmpilen? rawmpilen:1); if (!rawmpi) return gpg_err_code_from_syserror (); memcpy (rawmpi, buf, rawmpilen); reverse_buffer (rawmpi, rawmpilen); } else { /* Note: Without using an opaque MPI it is not reliable possible to find out whether the public key has been given in uncompressed format. Thus we expect native EdDSA format. */ rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL); if (!rawmpi) return gpg_err_code_from_syserror (); } if (rawmpilen) { sign = !!(rawmpi[0] & 0x80); rawmpi[0] &= 0x7f; } else sign = 0; _gcry_mpi_set_buffer (result->y, rawmpi, rawmpilen, 0); if (r_encpk) { /* Revert to little endian. */ if (sign && rawmpilen) rawmpi[0] |= 0x80; reverse_buffer (rawmpi, rawmpilen); *r_encpk = rawmpi; if (r_encpklen) *r_encpklen = rawmpilen; } else xfree (rawmpi); rc = _gcry_ecc_eddsa_recover_x (result->x, result->y, sign, ctx); mpi_set_ui (result->z, 1); return rc; }
/* * Test iterative X25519 computation through lower layer MPI routines. * * Input: K (as hex string), ITER, R (as hex string) * * where R is expected result of iterating X25519 by ITER times. * */ static void test_it (int testno, const char *k_str, int iter, const char *result_str) { gcry_ctx_t ctx; gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_mpi_t mpi_k = NULL; gcry_mpi_t mpi_x = NULL; gcry_mpi_point_t P = NULL; gcry_mpi_point_t Q; int i; gcry_mpi_t mpi_kk = NULL; if (verbose > 1) info ("Running test %d: iteration=%d\n", testno, iter); gcry_mpi_ec_new (&ctx, NULL, "Curve25519"); Q = gcry_mpi_point_new (0); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) { fail ("error scanning MPI for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error scanning MPI for test %d, %s: %s", testno, "x", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE); mpi_k = gcry_mpi_copy (mpi_x); if (debug) print_mpi ("k", mpi_k); for (i = 0; i < iter; i++) { /* * Another variant of decodeScalar25519 thing. */ mpi_kk = gcry_mpi_set (mpi_kk, mpi_k); gcry_mpi_set_bit (mpi_kk, 254); gcry_mpi_clear_bit (mpi_kk, 255); gcry_mpi_clear_bit (mpi_kk, 0); gcry_mpi_clear_bit (mpi_kk, 1); gcry_mpi_clear_bit (mpi_kk, 2); gcry_mpi_ec_mul (Q, mpi_kk, P, ctx); P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE); gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx); if (debug) print_mpi ("k", mpi_k); } { unsigned char res[32]; char *r, *r0; gcry_mpi_print (GCRYMPI_FMT_USG, res, 32, NULL, mpi_k); reverse_buffer (res, 32); r0 = r = xmalloc (65); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=0; i < 32; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("curv25519 failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: gcry_mpi_release (mpi_kk); gcry_mpi_release (mpi_k); gcry_mpi_point_release (P); gcry_mpi_release (mpi_x); xfree (buffer); gcry_mpi_point_release (Q); gcry_ctx_release (ctx); }
/* * Test X25519 functionality through higher layer crypto routines. * * Input: K (as hex string), U (as hex string), R (as hex string) * * where R is expected result of X25519 (K, U). * * It calls gcry_pk_decrypt with Curve25519 private key and let * it compute X25519. */ static void test_cv (int testno, const char *k_str, const char *u_str, const char *result_str) { gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_sexp_t s_pk = NULL; gcry_mpi_t mpi_k = NULL; gcry_sexp_t s_data = NULL; gcry_sexp_t s_result = NULL; gcry_sexp_t s_tmp = NULL; unsigned char *res = NULL; size_t res_len; if (verbose > 1) info ("Running test %d\n", testno); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_k, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error converting MPI for test %d: %s", testno, gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k))) { fail ("error building s-exp for test %d, %s: %s", testno, "data", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "u", "invalid hex string"); goto leave; } /* * The procedure of decodeUCoordinate will be done internally * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian * binary to build S-exp. * * We could add the prefix 0x40, but libgcrypt also supports * format with no prefix. So, it is OK not to put the prefix. */ if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Curve25519\")" " (flags djb-tweak)" " (q%b)))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, gpg_strerror (err)); s_tmp = gcry_sexp_find_token (s_result, "s", 0); if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value"); else { char *r, *r0; int i; /* To skip the prefix 0x40, for-loop start with i=1 */ r0 = r = xmalloc (2*(res_len)+1); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=1; i < res_len; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("gcry_pk_encrypt failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: xfree (res); gcry_mpi_release (mpi_k); gcry_sexp_release (s_tmp); gcry_sexp_release (s_result); gcry_sexp_release (s_data); gcry_sexp_release (s_pk); xfree (buffer); }