int digsig_init_pkey(const char read_par, unsigned char *raw_public_key, int mpi_size) { int nread; switch (read_par) { case 'n': DSM_PRINT(DEBUG_SIGN, "Reading raw_public_key_n!\n"); nread = mpi_size; digsig_public_key[0] = mpi_read_from_buffer(raw_public_key, &nread, 0); break; case 'e': DSM_PRINT(DEBUG_SIGN, "Reading raw_public_key_e!\n"); nread = mpi_size; digsig_public_key[1] = mpi_read_from_buffer(raw_public_key, &nread, 0); break; } return 0; }
int rsa_verify_sig(char *sig, int sig_size, u8 *sha1) { MPI public_key[2]; MPI hash; MPI data; int nread; int nframe; if (!rsa_key) { return -EINVAL; } /* initialize our keys */ nread = rsa_key->n_size; public_key[0] = mpi_read_from_buffer((byte *)rsa_key->n, &nread, 0); if (!public_key[0]) { return -EINVAL; } nread = rsa_key->e_size; public_key[1] = mpi_read_from_buffer((byte *)rsa_key->e, &nread, 0); if (!public_key[1]) { return -EINVAL; } /* set up the MPI for the sig */ data = mpi_read_from_buffer(sig, &sig_size, 0); if (!data) { return -EINVAL; } /* set up the MPI for the result */ nframe = mpi_get_nbits(public_key[0]); hash = do_encode_md(sha1, nframe); /* verify the sig */ return rsa_verify(hash, &data, public_key); }
void digsig_init_pkey_internal(void) { int buf_size; printk(KERN_DEBUG "digsig.keys_valid 0x%08x\n\n", digsig_keys.valid); dump_key("n_key", digsig_keys.n_key, 130); dump_key("e_key", digsig_keys.e_key, 5); if (digsig_keys.valid != 1) { printk(KERN_NOTICE "DIGSIG: no valid key, digsig security disabled\n"); return; } DSM_PRINT(DEBUG_SIGN, "Reading raw_public_key_n!\n"); /* * key size in bits encoded in first two bytes, big endian. * round key size up and convert to bytes. * add two bytes for the size field */ buf_size = digsig_keys.n_key[0] << 8 | digsig_keys.n_key[1]; buf_size = (buf_size + 7)/8; buf_size += 2; printk(KERN_INFO "%s: n_key size %d\n", __FUNCTION__, buf_size); digsig_public_key[0] = mpi_read_from_buffer(digsig_keys.n_key, &buf_size, 0); DSM_PRINT(DEBUG_SIGN, "Reading raw_public_key_e!\n"); buf_size = digsig_keys.e_key[0] << 8 | digsig_keys.e_key[1]; buf_size = (buf_size + 7)/8; buf_size += 2; printk(KERN_INFO "%s: e_key size %d\n", __FUNCTION__, buf_size); digsig_public_key[1] = mpi_read_from_buffer(digsig_keys.e_key, &buf_size, 0); g_init = 1; printk(KERN_NOTICE "DIGSIG: digsig security enabled\n"); }
int digsig_rsa_bsign_verify(unsigned char *hash_format, int length, unsigned char *signed_hash) { int rc = 0, cmp; MPI hash, data; unsigned nread = DIGSIG_ELF_SIG_SIZE; int nframe; unsigned char sig_class; unsigned char sig_timestamp[SIZEOF_UNSIGNED_INT]; int i; SIGCTX *ctx = NULL; unsigned char *new_sig; new_sig = kmalloc(gDigestLength[HASH_SHA1], DIGSIG_SAFE_ALLOC); if (!new_sig) { DSM_ERROR ("kmalloc failed in %s for new_sig\n", __FUNCTION__); return -ENOMEM; } /* Get MPI of signed data from .sig file/section */ nread = DIGSIG_ELF_SIG_SIZE; data = mpi_read_from_buffer(signed_hash + DIGSIG_RSA_DATA_OFFSET, &nread, 0); if (!data) { kfree(new_sig); return -EINVAL; } /* Get MPI for hash */ /* bsign modif - file hash - gpg modif */ /* bsign modif: add bsign greet at beginning */ /* gpg modif: add class and timestamp at end */ ctx = kmalloc(sizeof(SIGCTX), GFP_KERNEL); if (!ctx) { DSM_ERROR("Cannot allocate ctx\n"); mpi_free (data); kfree (new_sig); return -ENOMEM; } ctx->tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); if (!ctx->tvmem) { kfree (ctx); mpi_free(data); kfree (new_sig); DSM_ERROR("Cannot allocate plaintext buffer\n"); return -ENOMEM; } digsig_sha1_init(ctx); sig_class = signed_hash[DIGSIG_RSA_CLASS_OFFSET]; sig_class &= 0xff; for (i = 0; i < SIZEOF_UNSIGNED_INT; i++) { sig_timestamp[i] = signed_hash[DIGSIG_RSA_TIMESTAMP_OFFSET + i] & 0xff; } digsig_sha1_update(ctx, DIGSIG_BSIGN_STRING, DIGSIG_BSIGN_GREET_SIZE); digsig_sha1_update(ctx, hash_format, SHA1_DIGEST_LENGTH); digsig_sha1_update(ctx, &sig_class, 1); digsig_sha1_update(ctx, sig_timestamp, SIZEOF_UNSIGNED_INT); if ((rc = digsig_sha1_final(ctx, new_sig)) < 0) { DSM_ERROR ("internal_rsa_verify_final Cannot finalize hash algorithm\n"); mpi_free(data); kfree(ctx->tvmem); kfree(ctx); return rc; } nframe = mpi_get_nbits(digsig_public_key[0]); hash = do_encode_md(new_sig, nframe); if (hash == MPI_NULL) { DSM_PRINT(DEBUG_SIGN, "mpi creation failed\\n"); } /* Do RSA verification */ cmp = rsa_verify(hash, &data, digsig_public_key); rc = cmp ? -EPERM : 0; mpi_free(hash); mpi_free(data); kfree(ctx->tvmem); kfree(ctx); kfree (new_sig); return rc; }
/* Convert the external representation of an integer stored in BUFFER with a length of BUFLEN into a newly create MPI returned in RET_MPI. If NBYTES is not NULL, it will receive the number of bytes actually scanned after a successful operation. */ gcry_error_t gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, const void *buffer_arg, size_t buflen, size_t *nscanned) { const unsigned char *buffer = (const unsigned char*)buffer_arg; struct gcry_mpi *a = NULL; unsigned int len; int secure = (buffer && gcry_is_secure (buffer)); if (format == GCRYMPI_FMT_SSH) len = 0; else len = buflen; if (format == GCRYMPI_FMT_STD) { const unsigned char *s = buffer; a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) /BYTES_PER_MPI_LIMB) : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); if (len) { a->sign = !!(*s & 0x80); if (a->sign) { /* FIXME: we have to convert from 2compl to magnitude format */ mpi_free (a); return gcry_error (GPG_ERR_INTERNAL); } else _gcry_mpi_set_buffer (a, s, len, 0); } if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else if (format == GCRYMPI_FMT_USG) { a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) /BYTES_PER_MPI_LIMB) : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); if (len) _gcry_mpi_set_buffer (a, buffer, len, 0); if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else if (format == GCRYMPI_FMT_PGP) { a = mpi_read_from_buffer (buffer, &len, secure); if (nscanned) *nscanned = len; if (ret_mpi && a) { mpi_normalize (a); *ret_mpi = a; } else if (a) { mpi_free(a); a = NULL; } return a? 0 : gcry_error (GPG_ERR_INV_OBJ); } else if (format == GCRYMPI_FMT_SSH) { const unsigned char *s = buffer; size_t n; /* This test is not strictly necessary and an assert (!len) would be sufficient. We keep this test in case we later allow the BUFLEN argument to act as a sanitiy check. Same below. */ if (len && len < 4) return gcry_error (GPG_ERR_TOO_SHORT); n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); s += 4; if (len) len -= 4; if (len && n > len) return gcry_error (GPG_ERR_TOO_LARGE); a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1) /BYTES_PER_MPI_LIMB) : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); if (n) { a->sign = !!(*s & 0x80); if (a->sign) { /* FIXME: we have to convert from 2compl to magnitude format */ mpi_free(a); return gcry_error (GPG_ERR_INTERNAL); } else _gcry_mpi_set_buffer( a, s, n, 0 ); } if (nscanned) *nscanned = n+4; if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else if (format == GCRYMPI_FMT_HEX) { /* We can only handle C strings for now. */ if (buflen) return gcry_error (GPG_ERR_INV_ARG); a = secure? mpi_alloc_secure (0) : mpi_alloc(0); if (mpi_fromstr (a, (const char *)buffer)) { mpi_free (a); return gcry_error (GPG_ERR_INV_OBJ); } if (ret_mpi) { mpi_normalize ( a ); *ret_mpi = a; } else mpi_free(a); return 0; } else return gcry_error (GPG_ERR_INV_ARG); }