示例#1
0
文件: service.c 项目: Dimillian/wine
HRESULT service_pause_service( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
{
    VARIANT name, retval;
    IWbemClassObject *sig;
    HRESULT hr;

    TRACE("%p, %p, %p\n", obj, in, out);

    hr = IWbemClassObject_Get( obj, prop_nameW, 0, &name, NULL, NULL );
    if (hr != S_OK) return hr;

    hr = create_signature( class_serviceW, method_pauseserviceW, PARAM_OUT, &sig );
    if (hr != S_OK)
    {
        VariantClear( &name );
        return hr;
    }
    hr = IWbemClassObject_SpawnInstance( sig, 0, out );
    if (hr != S_OK)
    {
        VariantClear( &name );
        IWbemClassObject_Release( sig );
        return hr;
    }
    hr = control_service( V_BSTR(&name), SERVICE_CONTROL_PAUSE, &retval );
    if (hr != S_OK) goto done;
    hr = IWbemClassObject_Put( *out, param_returnvalueW, 0, &retval, CIM_UINT32 );

done:
    VariantClear( &name );
    IWbemClassObject_Release( sig );
    if (hr != S_OK) IWbemClassObject_Release( *out );
    return hr;
}
示例#2
0
/*@
 * @deftypemethod jit_function void create ()
 * Create this function if it doesn't already exist.  This version will
 * call the virtual @code{create_signature()} method to obtain the
 * signature from the subclass.
 * @end deftypemethod
@*/
void jit_function::create()
{
	if(!func)
	{
		jit_type_t signature = create_signature();
		create(signature);
		if(!func)
		{
			jit_type_free(signature);
		}
	}
}
示例#3
0
文件: process.c 项目: AlexSteel/wine
HRESULT process_get_owner( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
{
    VARIANT user, domain, retval;
    IWbemClassObject *sig, *out_params = NULL;
    HRESULT hr;

    TRACE("%p, %p, %p\n", obj, in, out);

    hr = create_signature( class_processW, method_getownerW, PARAM_OUT, &sig );
    if (hr != S_OK) return hr;

    if (out)
    {
        hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
        if (hr != S_OK)
        {
            IWbemClassObject_Release( sig );
            return hr;
        }
    }
    VariantInit( &user );
    VariantInit( &domain );
    hr = get_owner( &user, &domain, &retval );
    if (hr != S_OK) goto done;
    if (out_params)
    {
        if (!V_UI4( &retval ))
        {
            hr = IWbemClassObject_Put( out_params, param_userW, 0, &user, CIM_STRING );
            if (hr != S_OK) goto done;
            hr = IWbemClassObject_Put( out_params, param_domainW, 0, &domain, CIM_STRING );
            if (hr != S_OK) goto done;
        }
        hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
    }

done:
    VariantClear( &user );
    VariantClear( &domain );
    IWbemClassObject_Release( sig );
    if (hr == S_OK && out)
    {
        *out = out_params;
        IWbemClassObject_AddRef( out_params );
    }
    if (out_params) IWbemClassObject_Release( out_params );
    return hr;
}
示例#4
0
文件: reg.c 项目: ZoloZiak/reactos
HRESULT reg_get_stringvalue( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
{
    VARIANT defkey, subkey, name, value, retval;
    IWbemClassObject *sig;
    HRESULT hr;

    TRACE("%p, %p\n", in, out);

    hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
    if (hr != S_OK) return hr;
    hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
    if (hr != S_OK) return hr;
    hr = IWbemClassObject_Get( in, param_valuenameW, 0, &name, NULL, NULL );
    if (hr != S_OK) return hr;

    hr = create_signature( class_stdregprovW, method_getstringvalueW, PARAM_OUT, &sig );
    if (hr != S_OK)
    {
        VariantClear( &name );
        VariantClear( &subkey );
        return hr;
    }
    hr = IWbemClassObject_SpawnInstance( sig, 0, out );
    if (hr != S_OK)
    {
        VariantClear( &name );
        VariantClear( &subkey );
        IWbemClassObject_Release( sig );
        return hr;
    }
    VariantInit( &value );
    hr = get_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, &retval );
    if (hr != S_OK) goto done;
    if (!V_UI4( &retval ))
    {
        hr = IWbemClassObject_Put( *out, param_valueW, 0, &value, CIM_STRING );
        if (hr != S_OK) goto done;
    }
    hr = IWbemClassObject_Put( *out, param_returnvalueW, 0, &retval, CIM_UINT32 );

done:
    VariantClear( &name );
    VariantClear( &subkey );
    IWbemClassObject_Release( sig );
    if (hr != S_OK) IWbemClassObject_Release( *out );
    return hr;
}
示例#5
0
文件: service.c 项目: RPG-7/reactos
HRESULT service_stop_service( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
{
    VARIANT name, retval;
    IWbemClassObject *sig, *out_params = NULL;
    HRESULT hr;

    TRACE("%p, %p, %p\n", obj, in, out);

    hr = IWbemClassObject_Get( obj, prop_nameW, 0, &name, NULL, NULL );
    if (hr != S_OK) return hr;

    hr = create_signature( class_serviceW, method_stopserviceW, PARAM_OUT, &sig );
    if (hr != S_OK)
    {
        VariantClear( &name );
        return hr;
    }
    if (out)
    {
        hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
        if (hr != S_OK)
        {
            VariantClear( &name );
            IWbemClassObject_Release( sig );
            return hr;
        }
    }
    hr = control_service( V_BSTR(&name), SERVICE_CONTROL_STOP, &retval );
    if (hr != S_OK) goto done;

    if (out_params)
        hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );

done:
    VariantClear( &name );
    IWbemClassObject_Release( sig );
    if (hr == S_OK && out)
    {
        *out = out_params;
        IWbemClassObject_AddRef( out_params );
    }
    if (out_params) IWbemClassObject_Release( out_params );
    return hr;
}
示例#6
0
文件: v4.c 项目: QuentinPerez/Droplet
static dpl_status_t
dpl_s3_insert_signature_v4_params(const dpl_req_t *req, dpl_dict_t *query_params,
                                  struct tm *tm, char *date_str, char *signature)
{
  int           item;
  dpl_status_t  ret;
  dpl_vec_t     *canonical_params;
  char          canonical_request[4096] = "";
  char          sign_request[1024] = "";

  canonical_params = get_canonical_params(req->subresource, query_params, 0);
  if (canonical_params == NULL)
    return DPL_FAILURE;

  ret = create_canonical_request(req, NULL, NULL, canonical_params,
                                 canonical_request, sizeof(canonical_request));

  if (ret == DPL_SUCCESS) {
    DPRINTF("Canonical request:\n%s\n", canonical_request);
    ret = create_sign_request(req, canonical_request, tm, date_str,
                              sign_request, sizeof(sign_request));
  }

  if (ret == DPL_SUCCESS) {
    DPRINTF("Signing request:\n%s\n", sign_request);
    ret = create_signature(req, tm, sign_request, signature);
  }

  if (ret == DPL_SUCCESS)
    DPRINTF("Signature: %s\n", signature);

  for (item = 0; item < canonical_params->n_items; item++) {
    dpl_dict_var_t    *param = (dpl_dict_var_t *) dpl_vec_get(canonical_params, item);
    free(param->key);
    dpl_dict_var_free(param);
  }
  dpl_vec_free(canonical_params);

  return ret;
}
示例#7
0
    bool AssociatedRelayConsumer::check_authentication(const std::multimap<std::string, std::string> &params) {
        // Try to find our assoc handle.
        const std::string *assoc_handle_ptr = lookup_assoc_handle(openid_provider());
        if(!assoc_handle_ptr)
            assoc_handle_ptr = associate();
        
        // If the handle is "DUMB", we have to fall back to the dumb consumer.
        if(assoc_handle_ptr->compare("DUMB") == 0) {
            delete assoc_handle_ptr;
            return DumbRelayConsumer::check_authentication(params);
        }
        
        // Move the string to the stack, so that return can free it.
        std::string assoc_handle(*assoc_handle_ptr);
        delete assoc_handle_ptr;
        
        // Not possible to be missing the assoc_handle
        std::multimap<std::string, std::string>::const_iterator assoc_iter = params.find(std::string("openid.assoc_handle"));
        if(assoc_iter == params.end())
            return false;

        if(assoc_handle.compare(assoc_iter->second) == 0) {
            // make sure this request was signed.
            std::multimap<std::string, std::string>::const_iterator sig_iter = params.find(std::string("openid.sig"));
            if(sig_iter == params.end())
                return false;
            std::string their_signature(sig_iter->second);
            
            // Look for the signed fields.
            sig_iter = params.find(std::string("openid.signed"));
            if(sig_iter == params.end())
                return false;
            std::string signed_params(sig_iter->second), key;
            
            // construct the message that was signed.
            std::ostringstream message;
            std::string::const_iterator iter = signed_params.begin();
            while(iter != signed_params.end()) {
                char c = *iter;
                ++iter;
                
                // We hit a non-key character, 
                if(c == '\n' || c == ',' || iter == signed_params.end()) {
                    // store the last char in the string.
                    if(iter == signed_params.end()) key.push_back(c);
                    // look for the param
                    std::string key_to_find("openid.");
                    key_to_find.append(key);
                    sig_iter = params.find(key_to_find);
                    if(sig_iter == params.end())
                        return false;
                    
                    // add to the message data.
                    message << key << ":" << sig_iter->second << "\n";
                    
                    // clear the key to start over.
                    key.clear();
                } else {
                    key.push_back(c);
                }
            }
            
            // attempt to recreate the signature.
            Association *assoc = lookup_association(assoc_handle);
            if(!assoc)
                return false;
            std::string our_signature(create_signature(message.str(), assoc->secret));
            delete assoc;

            // Test that the signature created matches the one given.
            return (their_signature.compare(our_signature) == 0);
            
        } else if(assoc_handle.compare(assoc_iter->second) != 0 &&
           (assoc_iter = params.find("openid.invalidate_handle")) != params.end()) {
            
            // Prepare the verification post data.
            std::ostringstream data;
            CURL *curl = new_curl_handle();
            data << "openid.mode=check_authentication";
            for(std::multimap<std::string, std::string>::const_iterator iter = params.begin();
                iter != params.end();
                ++iter) {
                if(iter->first.compare("openid.mode") == 0) continue;
                
                char *tmp;
                tmp = curl_easy_escape(curl, iter->first.c_str(), iter->first.size());
                data << "&" << tmp << "=";
                curl_free(tmp);
                
                tmp = curl_easy_escape(curl, iter->second.c_str(), iter->second.size());
                data << tmp;
                curl_free(tmp);
            }
            // Clean up after curl.
            curl_easy_cleanup(curl);
            
            // execute.
            std::string content = contact_openid_provider(data.str());
            
            // Check for invalidating the handle.
            std::string invalidate_substring("\ninvalidate_handle:");
            invalidate_substring.append(assoc_iter->second).append("\n");
            if(content.find(invalidate_substring) != content.npos)
                invalidate_assoc_handle(assoc_iter->second);
            
            // Test for is_valid.
            return content.find("\nis_valid:true\n") != content.npos;
        }
        
        // If we didn't match any other cases, return false.
        return false;
    }
示例#8
0
/*
Returns -1 if somethings fails otherwise 0
*/
int sign_image(char* in, char* out){

	/*
	An int is enough because the partitions shouldn't be bigger than 4GB
	*/
	int finalimagesize = 0;
	/*
	Load an image at given path
	*/
	FILE *imageinput;
	imageinput = fopen(in, "rb");

	if (imageinput == NULL){
		std::cerr << "[ ERROR ] Image does not exist at given location" << std::endl;
		return -1;
	}

	/*
	Check if file has contents
	*/
	unsigned imagefilesize = get_file_size(imageinput);
	if (imagefilesize == 0){
		std::cerr << "[ ERROR ] Image has no size" << std::endl;
		return -1;
	}

	/*
	Extract image header first to determine if the final image is bigger than the orignal
	*/
	boot_img_hdr* hdr = NULL;
	hdr = (boot_img_hdr*)malloc(sizeof(boot_img_hdr));
	fread(hdr, sizeof(boot_img_hdr), 1, imageinput);

	/*
	Reposition pointer at start
	*/
	fseek(imageinput, 0, SEEK_SET);


	/*
	Check if image is an Android bootimage
	*/
	if (memcmp((char*)hdr->magic, "ANDROID!", 8) != 0){
		std::cerr << "[ ERROR ] File is not an Android boot image" << std::endl;
		return -1;
	}

	/*
	Load necessary variables from header and delete header
	*/
	unsigned kernel_actual;
	unsigned ramdisk_actual;
	unsigned imagesize_actual;
	unsigned dt_actual;
	unsigned page_size = hdr->page_size;
	unsigned page_mask = hdr->page_size - 1;

	kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
	dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
	free(hdr);

	/*
	Calculate size of the "real" image
	*/
	imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);

	/*
	If the "real" image is bigger than the file, the file is probably corrupted
	*/
	if (imagefilesize < imagesize_actual){
		std::cerr << "[ ERROR ] File is invalid (is it corrupted?)" << std::endl;
		return -1;
	}

	/*
	If the file is smaller than the "real" image + one page, a buffer with the size of the image would be too small we need allocate a new bigger one
	*/
	if (imagefilesize < imagesize_actual + page_size){
		finalimagesize = imagefilesize + page_size;
	} else {
		finalimagesize = imagefilesize;
	}

	/*
	Load image in buffer and close file
	*/
	unsigned char* image = NULL;
	image = (unsigned char*)malloc(finalimagesize);
	fread(image, 1, imagefilesize, imageinput);
	fclose(imageinput);


	/*
	Create output file
	*/
	FILE *imageoutput;
	imageoutput = fopen(out, "wb");

	if (imageoutput == NULL){
		std::cerr << "[ ERROR ] Can't write output image to disk" << std::endl;
		return -1;
	}

	/*
	Hash the real image
	*/
	unsigned char hash[65];
	unsigned char signature[SIGNATURE_SIZE];
	memset(signature, 0, SIGNATURE_SIZE);
	sha256_buffer(image, imagesize_actual, hash);

	/*
	Create signature with given hash
	*/
	int sig = create_signature(hash, signature);

	/*
	If the signature is created successfully AND the signature passes the check, the signature will be written into the image buffer, which will written to the output file
	*/
	if (sig != -1){
		std::cerr << std::endl << "[ STATUS ] Checking created signature... ";
		if (verify_image(image, signature, imagesize_actual) == 0){
			memcpy(image + imagesize_actual, signature, SIGNATURE_SIZE);
			fwrite(image, finalimagesize, 1, imageoutput);
		}
	} 

	/*
	Cleanup
	*/
	fclose(imageoutput);
	free(image);

	/*
	Final check of the output file
	*/
	std::cerr << std::endl << "[ STATUS ] Checking created image... ";
	check_image(out);

	return 0;
}
示例#9
0
文件: v4.c 项目: QuentinPerez/Droplet
dpl_status_t
dpl_s3_add_authorization_v4_to_headers(const dpl_req_t *req,
                                       dpl_dict_t *headers,
                                       const dpl_dict_t *query_params,
                                       struct tm *i_tm)
{
  int           item;
  dpl_status_t  ret;
  char          canonical_request[4096] = "";
  char          sign_request[1024] = "";
  char          signature[DPL_HEX_LENGTH(SHA256_DIGEST_LENGTH) + 1];
  char          authorization[1024] = "";
  char          date_str[32] = "";
  dpl_vec_t     *canonical_headers;
  dpl_vec_t     *canonical_params;
  struct tm     tm;

  ret = add_payload_signature_to_headers(req, headers);
  if (ret != DPL_SUCCESS)
    return ret;

  ret = get_current_utc_date(&tm, i_tm, date_str, sizeof(date_str));
  if (ret != DPL_SUCCESS)
    return ret;

  ret = dpl_dict_add(headers, "x-amz-date", date_str, 0);
  if (ret != DPL_SUCCESS)
    return ret;

  canonical_headers = get_canonical_headers(headers);
  if (canonical_headers == NULL)
    return DPL_FAILURE;

  canonical_params = get_canonical_params(req->subresource, query_params, 1);
  if (canonical_params == NULL) {
    dpl_vec_free(canonical_headers);
    return DPL_FAILURE;
  }

  ret = create_canonical_request(req, headers,
                                 canonical_headers, canonical_params,
                                 canonical_request, sizeof(canonical_request));

  if (ret == DPL_SUCCESS) {
    DPRINTF("Canonical request:\n%s\n", canonical_request);
    ret = create_sign_request(req, canonical_request, &tm, date_str,
                              sign_request, sizeof(sign_request));
  }

  if (ret == DPL_SUCCESS) {
    DPRINTF("Signing request:\n%s\n", sign_request);
    ret = create_signature(req, &tm, sign_request, signature);
  }

  if (ret == DPL_SUCCESS) {
    DPRINTF("Signature: %s\n", signature);
    ret = create_authorization(req, &tm, canonical_headers, signature,
                               authorization, sizeof(authorization));
  }

  if (ret == DPL_SUCCESS)
    ret = dpl_dict_add(headers, "Authorization", authorization, 0);

  for (item = 0; item < canonical_params->n_items; item++) {
    dpl_dict_var_t    *param = (dpl_dict_var_t *) dpl_vec_get(canonical_params, item);
    free(param->key);
    dpl_dict_var_free(param);
  }
  dpl_vec_free(canonical_params);
  dpl_vec_free(canonical_headers);

  return ret;
}
示例#10
0
bool test() {
  unsigned char buf[256], sig[256], buf2[8];
  unsigned long address, count, chipsize, blocksize;
  unsigned long usec;
  bool first;

  // Read the chip identification
  Serial.println();
  Serial.println("Read Chip Identification:");
  SerialFlash.readID(buf);
  Serial.print("  JEDEC ID:     ");
  Serial.print(buf[0], HEX);
  Serial.print(" ");
  Serial.print(buf[1], HEX);
  Serial.print(" ");
  Serial.println(buf[2], HEX);
  Serial.print("  Part Nummber: ");
  Serial.println(id2chip(buf));
  Serial.print("  Memory Size:  ");
  chipsize = SerialFlash.capacity(buf);
  Serial.print(chipsize);
  Serial.println(" bytes");
  if (chipsize == 0) return false;
  Serial.print("  Block Size:   ");
  blocksize = SerialFlash.blockSize();
  Serial.print(blocksize);
  Serial.println(" bytes");


  // Read the entire chip.  Every test location must be
  // erased, or have a previously tested signature
  Serial.println();
  Serial.println("Reading Chip...");
  memset(buf, 0, sizeof(buf));
  memset(sig, 0, sizeof(sig));
  memset(buf2, 0, sizeof(buf2));
  address = 0;
  count = 0;
  first = true;
  while (address < chipsize) {
    SerialFlash.read(address, buf, 8);
    //Serial.print("  addr = ");
    //Serial.print(address, HEX);
    //Serial.print(", data = ");
    //printbuf(buf, 8);
    create_signature(address, sig);
    if (is_erased(buf, 8) == false) {
      if (equal_signatures(buf, sig) == false) {
        Serial.print("  Previous data found at address ");
        Serial.println(address);
        Serial.println("  You must fully erase the chip before this test");
        Serial.print("  found this: ");
        printbuf(buf, 8);
        Serial.print("     correct: ");
        printbuf(sig, 8);
        return false;
      }
    } else {
      count = count + 1; // number of blank signatures
    }
    if (first) {
      address = address + (testIncrement - 8);
      first = false;
    } else {
      address = address + 8;
      first = true;
    }
  }


  // Write any signatures that were blank on the original check
  if (count > 0) {
    Serial.println();
    Serial.print("Writing ");
    Serial.print(count);
    Serial.println(" signatures");
    memset(buf, 0, sizeof(buf));
    memset(sig, 0, sizeof(sig));
    memset(buf2, 0, sizeof(buf2));
    address = 0;
    first = true;
    while (address < chipsize) {
      SerialFlash.read(address, buf, 8);
      if (is_erased(buf, 8)) {
        create_signature(address, sig);
        //Serial.printf("write %08X: data: ", address);
        //printbuf(sig, 8);
        SerialFlash.write(address, sig, 8);
        while (!SerialFlash.ready()) ; // wait
        SerialFlash.read(address, buf, 8);
        if (equal_signatures(buf, sig) == false) {
          Serial.print("  error writing signature at ");
          Serial.println(address);
          Serial.print("  Read this: ");
          printbuf(buf, 8);
          Serial.print("  Expected:  ");
          printbuf(sig, 8);
          return false;
        }
      }
      if (first) {
        address = address + (testIncrement - 8);
        first = false;
      } else {
        address = address + 8;
        first = true;
      }
    }
  } else {
    Serial.println("  all signatures present from prior tests");
  }


  // Read all the signatures again, just to be sure
  // checks prior writing didn't corrupt any other data
  Serial.println();
  Serial.println("Double Checking All Signatures:");
  memset(buf, 0, sizeof(buf));
  memset(sig, 0, sizeof(sig));
  memset(buf2, 0, sizeof(buf2));
  count = 0;
  address = 0;
  first = true;
  while (address < chipsize) {
    SerialFlash.read(address, buf, 8);
    create_signature(address, sig);
    if (equal_signatures(buf, sig) == false) {
      Serial.print("  error in signature at ");
      Serial.println(address);
      Serial.print("  Read this: ");
      printbuf(buf, 8);
      Serial.print("  Expected:  ");
      printbuf(sig, 8);
      return false;
    }
    count = count + 1;
    if (first) {
      address = address + (testIncrement - 8);
      first = false;
    } else {
      address = address + 8;
      first = true;
    }
  }
  Serial.print("  all ");
  Serial.print(count);
  Serial.println(" signatures read ok");


  // Read pairs of adjacent signatures
  // check read works across boundaries
  Serial.println();
  Serial.println("Checking Signature Pairs");
  memset(buf, 0, sizeof(buf));
  memset(sig, 0, sizeof(sig));
  memset(buf2, 0, sizeof(buf2));
  count = 0;
  address = testIncrement - 8;
  first = true;
  while (address < chipsize - 8) {
    SerialFlash.read(address, buf, 16);
    create_signature(address, sig);
    create_signature(address + 8, sig + 8);
    if (memcmp(buf, sig, 16) != 0) {
      Serial.print("  error in signature pair at ");
      Serial.println(address);
      Serial.print("  Read this: ");
      printbuf(buf, 16);
      Serial.print("  Expected:  ");
      printbuf(sig, 16);
      return false;
    }
    count = count + 1;
    address = address + testIncrement;
  }
  Serial.print("  all ");
  Serial.print(count);
  Serial.println(" signature pairs read ok");


  // Write data and read while write in progress
  Serial.println();
  Serial.println("Checking Read-While-Write (Program Suspend)");
  address = 256;
  while (address < chipsize) { // find a blank space
    SerialFlash.read(address, buf, 256);
    if (is_erased(buf, 256)) break;
    address = address + 256;
  }
  if (address >= chipsize) {
    Serial.println("  error, unable to find any blank space!");
    return false;
  }
  for (int i=0; i < 256; i += 8) {
    create_signature(address + i, sig + i);
  }
  Serial.print("  write 256 bytes at ");
  Serial.println(address);
  Serial.flush();
  SerialFlash.write(address, sig, 256);
  usec = micros();
  if (SerialFlash.ready()) {
    Serial.println("  error, chip did not become busy after write");
    return false;
  }
  SerialFlash.read(0, buf2, 8); // read while busy writing
  while (!SerialFlash.ready()) ; // wait
  usec = micros() - usec;
  Serial.print("  write time was ");
  Serial.print(usec);
  Serial.println(" microseconds.");
  SerialFlash.read(address, buf, 256);
  if (memcmp(buf, sig, 256) != 0) {
    Serial.println("  error writing to flash");
    Serial.print("  Read this: ");
    printbuf(buf, 256);
    Serial.print("  Expected:  ");
    printbuf(sig, 256);
    return false;
  }
  create_signature(0, sig);
  if (memcmp(buf2, sig, 8) != 0) {
    Serial.println("  error, incorrect read while writing");
    Serial.print("  Read this: ");
    printbuf(buf2, 256);
    Serial.print("  Expected:  ");
    printbuf(sig, 256);
    return false;
  }
  Serial.print("  read-while-writing: ");
  printbuf(buf2, 8);
  Serial.println("  test passed, good read while writing");



  // Erase a block and read while erase in progress
  if (chipsize >= 262144 + blocksize + testIncrement) {
    Serial.println();
    Serial.println("Checking Read-While-Erase (Erase Suspend)");
    memset(buf, 0, sizeof(buf));
    memset(sig, 0, sizeof(sig));
    memset(buf2, 0, sizeof(buf2));
    SerialFlash.eraseBlock(262144);
    usec = micros();
    delayMicroseconds(50);
    if (SerialFlash.ready()) {
      Serial.println("  error, chip did not become busy after erase");
      return false;
    }
    SerialFlash.read(0, buf2, 8); // read while busy writing
    while (!SerialFlash.ready()) ; // wait
    usec = micros() - usec;
    Serial.print("  erase time was ");
    Serial.print(usec);
    Serial.println(" microseconds.");
    // read all signatures, check ones in this block got
    // erased, and all the others are still intact
    address = 0;
    first = true;
    while (address < chipsize) {
      SerialFlash.read(address, buf, 8);
      if (address >= 262144 && address < 262144 + blocksize) {
        if (is_erased(buf, 8) == false) {
          Serial.print("  error in erasing at ");
          Serial.println(address);
          Serial.print("  Read this: ");
          printbuf(buf, 8);
          return false;
        }
      } else {
        create_signature(address, sig);
        if (equal_signatures(buf, sig) == false) {
          Serial.print("  error in signature at ");
          Serial.println(address);
          Serial.print("  Read this: ");
          printbuf(buf, 8);
          Serial.print("  Expected:  ");
          printbuf(sig, 8);
          return false;
        }
      }
      if (first) {
        address = address + (testIncrement - 8);
        first = false;
      } else {
        address = address + 8;
        first = true;
      }
    }
    Serial.print("  erase correctly erased ");
    Serial.print(blocksize);
    Serial.println(" bytes");
    // now check if the data we read during erase is good
    create_signature(0, sig);
    if (memcmp(buf2, sig, 8) != 0) {
      Serial.println("  error, incorrect read while erasing");
      Serial.print("  Read this: ");
      printbuf(buf2, 256);
      Serial.print("  Expected:  ");
      printbuf(sig, 256);
      return false;
    }
    Serial.print("  read-while-erasing: ");
    printbuf(buf2, 8);
    Serial.println("  test passed, good read while erasing");

  } else {
    Serial.println("Skip Read-While-Erase, this chip is too small");
  }




  return true;
}