/* Do PKCS-1 RSA encryption. * params is modulus, public exp. */ int _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, mpi_t * params, unsigned params_len, unsigned btype) { unsigned int i, pad; int ret; mpi_t m, res; opaque *edata, *ps; size_t k, psize; size_t mod_bits; mod_bits = _gnutls_mpi_get_nbits (params[0]); k = mod_bits / 8; if (mod_bits % 8 != 0) k++; if (plaintext->size > k - 11) { gnutls_assert (); return GNUTLS_E_PK_ENCRYPTION_FAILED; } edata = gnutls_alloca (k); if (edata == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* EB = 00||BT||PS||00||D * (use block type 'btype') */ edata[0] = 0; edata[1] = btype; psize = k - 3 - plaintext->size; ps = &edata[2]; switch (btype) { case 2: /* using public key */ if (params_len < RSA_PUBLIC_PARAMS) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } if (gc_pseudo_random (ps, psize) != GC_OK) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_RANDOM_FAILED; } for (i = 0; i < psize; i++) while (ps[i] == 0) { if (gc_pseudo_random (&ps[i], 1) != GC_OK) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_RANDOM_FAILED; } } break; case 1: /* using private key */ if (params_len < RSA_PRIVATE_PARAMS) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } for (i = 0; i < psize; i++) ps[i] = 0xff; break; default: gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } ps[psize] = 0; memcpy (&ps[psize + 1], plaintext->data, plaintext->size); if (_gnutls_mpi_scan_nz (&m, edata, &k) != 0) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_MPI_SCAN_FAILED; } gnutls_afree (edata); if (btype == 2) /* encrypt */ ret = _gnutls_pk_encrypt (GCRY_PK_RSA, &res, m, params, params_len); else /* sign */ ret = _gnutls_pk_sign (GCRY_PK_RSA, &res, m, params, params_len); _gnutls_mpi_release (&m); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_mpi_print (NULL, &psize, res); if (psize < k) { /* padding psize */ pad = k - psize; psize = k; } else if (psize == k) { pad = 0; } else { /* psize > k !!! */ /* This is an impossible situation */ gnutls_assert (); _gnutls_mpi_release (&res); return GNUTLS_E_INTERNAL_ERROR; } ciphertext->data = gnutls_malloc (psize); if (ciphertext->data == NULL) { gnutls_assert (); _gnutls_mpi_release (&res); return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_print (&ciphertext->data[pad], &psize, res); for (i = 0; i < pad; i++) ciphertext->data[i] = 0; ciphertext->size = k; _gnutls_mpi_release (&res); return 0; }
/** * gnutls_global_init - This function initializes the global data to defaults. * * This function initializes the global data to defaults. * Every gnutls application has a global data which holds common parameters * shared by gnutls session structures. * You must call gnutls_global_deinit() when gnutls usage is no longer needed * Returns zero on success. * * Note that this function will also initialize libgcrypt, if it has not * been initialized before. Thus if you want to manually initialize libgcrypt * you must do it before calling this function. This is useful in cases you * want to disable libgcrypt's internal lockings etc. * * This function increment a global counter, so that * gnutls_global_deinit() only releases resources when it has been * called as many times as gnutls_global_init(). This is useful when * GnuTLS is used by more than one library in an application. This * function can be called many times, but will only do something the * first time. * * Note! This function is not thread safe. If two threads call this * function simultaneously, they can cause a race between checking * the global counter and incrementing it, causing both threads to * execute the library initialization code. That would lead to a * memory leak. To handle this, your application could invoke this * function after aquiring a thread mutex. To ignore the potential * memory leak is also an option. * **/ int gnutls_global_init (void) { int result = 0; int res; char c; if (_gnutls_init++) goto out; #if HAVE_WINSOCK { WORD requested; WSADATA data; int err; requested = MAKEWORD (1, 1); err = WSAStartup (requested, &data); if (err != 0) { _gnutls_debug_log ("WSAStartup failed: %d.\n", err); return GNUTLS_E_LIBRARY_VERSION_MISMATCH; } if (data.wVersion < requested) { _gnutls_debug_log ("WSAStartup version check failed (%d < %d).\n", data.wVersion, requested); WSACleanup (); return GNUTLS_E_LIBRARY_VERSION_MISMATCH; } } #endif bindtextdomain (PACKAGE, LOCALEDIR); if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0) { const char *p; p = strchr (GNUTLS_GCRYPT_VERSION, ':'); if (p == NULL) p = GNUTLS_GCRYPT_VERSION; else p++; if (gcry_check_version (p) == NULL) { gnutls_assert (); _gnutls_debug_log ("Checking for libgcrypt failed '%s'\n", p); return GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY; } /* for gcrypt in order to be able to allocate memory */ gcry_set_allocation_handler (gnutls_malloc, gnutls_secure_malloc, _gnutls_is_secure_memory, gnutls_realloc, gnutls_free); /* gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING, NULL, 0); */ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0); #ifdef DEBUG /* applications may want to override that, so we only use * it in debugging mode. */ gcry_set_log_handler (_gnutls_gcry_log_handler, NULL); #endif } if (gc_init () != GC_OK) { gnutls_assert (); _gnutls_debug_log ("Initializing crypto backend failed\n"); return GNUTLS_E_INCOMPATIBLE_CRYPTO_LIBRARY; } /* for gcrypt in order to be able to allocate memory */ gc_set_allocators (gnutls_malloc, gnutls_secure_malloc, _gnutls_is_secure_memory, gnutls_realloc, gnutls_free); #ifdef DEBUG gnutls_global_set_log_function (dlog); #endif /* initialize parser * This should not deal with files in the final * version. */ if (asn1_check_version (GNUTLS_LIBTASN1_VERSION) == NULL) { gnutls_assert (); return GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY; } res = asn1_array2tree (pkix_asn1_tab, &_gnutls_pkix1_asn, NULL); if (res != ASN1_SUCCESS) { result = _gnutls_asn2err (res); goto out; } res = asn1_array2tree (gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL); if (res != ASN1_SUCCESS) { asn1_delete_structure (&_gnutls_pkix1_asn); result = _gnutls_asn2err (res); goto out; } /* Initialize the gcrypt (if used random generator) */ gc_pseudo_random (&c, 1); out: return result; }