From 4616413b7117ac9f7867a60408f79b8e9e8d1d52 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Fri, 23 Aug 2013 15:51:00 -0400 Subject: [PATCH 01/87] Bug 784739 - Switch from NULL to nullptr in image/. r=ehsan --- image/build/nsImageModule.cpp | 22 ++++++++-------- image/decoders/icon/gtk/nsIconChannel.cpp | 32 ++++++++++++----------- image/decoders/icon/nsIconModule.cpp | 12 ++++----- image/decoders/icon/win/nsIconChannel.cpp | 10 +++---- image/decoders/nsPNGDecoder.cpp | 25 +++++++++--------- image/decoders/nsPNGDecoder.h | 2 +- image/src/DiscardTracker.cpp | 4 +-- image/src/RasterImage.cpp | 4 +-- image/src/imgFrame.cpp | 2 +- image/src/imgLoader.cpp | 10 +++---- 10 files changed, 63 insertions(+), 60 deletions(-) diff --git a/image/build/nsImageModule.cpp b/image/build/nsImageModule.cpp index 20affea186f..a01ec0c2e1f 100644 --- a/image/build/nsImageModule.cpp +++ b/image/build/nsImageModule.cpp @@ -39,14 +39,14 @@ NS_DEFINE_NAMED_CID(NS_PNGENCODER_CID); NS_DEFINE_NAMED_CID(NS_BMPENCODER_CID); static const mozilla::Module::CIDEntry kImageCIDs[] = { - { &kNS_IMGLOADER_CID, false, NULL, imgLoaderConstructor, }, - { &kNS_IMGREQUESTPROXY_CID, false, NULL, imgRequestProxyConstructor, }, - { &kNS_IMGTOOLS_CID, false, NULL, imgToolsConstructor, }, - { &kNS_ICOENCODER_CID, false, NULL, nsICOEncoderConstructor, }, - { &kNS_JPEGENCODER_CID, false, NULL, nsJPEGEncoderConstructor, }, - { &kNS_PNGENCODER_CID, false, NULL, nsPNGEncoderConstructor, }, - { &kNS_BMPENCODER_CID, false, NULL, nsBMPEncoderConstructor, }, - { NULL } + { &kNS_IMGLOADER_CID, false, nullptr, imgLoaderConstructor, }, + { &kNS_IMGREQUESTPROXY_CID, false, nullptr, imgRequestProxyConstructor, }, + { &kNS_IMGTOOLS_CID, false, nullptr, imgToolsConstructor, }, + { &kNS_ICOENCODER_CID, false, nullptr, nsICOEncoderConstructor, }, + { &kNS_JPEGENCODER_CID, false, nullptr, nsJPEGEncoderConstructor, }, + { &kNS_PNGENCODER_CID, false, nullptr, nsPNGEncoderConstructor, }, + { &kNS_BMPENCODER_CID, false, nullptr, nsBMPEncoderConstructor, }, + { nullptr } }; static const mozilla::Module::ContractIDEntry kImageContracts[] = { @@ -58,7 +58,7 @@ static const mozilla::Module::ContractIDEntry kImageContracts[] = { { "@mozilla.org/image/encoder;2?type=" IMAGE_JPEG, &kNS_JPEGENCODER_CID }, { "@mozilla.org/image/encoder;2?type=" IMAGE_PNG, &kNS_PNGENCODER_CID }, { "@mozilla.org/image/encoder;2?type=" IMAGE_BMP, &kNS_BMPENCODER_CID }, - { NULL } + { nullptr } }; static const mozilla::Module::CategoryEntry kImageCategories[] = { @@ -74,7 +74,7 @@ static const mozilla::Module::CategoryEntry kImageCategories[] = { { "Gecko-Content-Viewers", IMAGE_PNG, "@mozilla.org/content/document-loader-factory;1" }, { "Gecko-Content-Viewers", IMAGE_X_PNG, "@mozilla.org/content/document-loader-factory;1" }, { "content-sniffing-services", "@mozilla.org/image/loader;1", "@mozilla.org/image/loader;1" }, - { NULL } + { nullptr } }; static nsresult @@ -98,7 +98,7 @@ static const mozilla::Module kImageModule = { kImageCIDs, kImageContracts, kImageCategories, - NULL, + nullptr, imglib_Initialize, imglib_Shutdown }; diff --git a/image/decoders/icon/gtk/nsIconChannel.cpp b/image/decoders/icon/gtk/nsIconChannel.cpp index caaa0a9c710..b21ac830dbf 100644 --- a/image/decoders/icon/gtk/nsIconChannel.cpp +++ b/image/decoders/icon/gtk/nsIconChannel.cpp @@ -268,7 +268,7 @@ GetIconSize(nsIMozIconURI *aIconURI) int size; GtkIconSize icon_size = moz_gtk_icon_size(iconSizeString.get()); - gtk_icon_size_lookup(icon_size, &size, NULL); + gtk_icon_size_lookup(icon_size, &size, nullptr); return size; } } @@ -328,7 +328,8 @@ nsIconChannel::InitWithGnome(nsIMozIconURI *aIconURI) } char* empty[] = { "" }; - _gnome_init(NS_ConvertUTF16toUTF8(appName).get(), "1.0", 1, empty, NULL, 0, NULL); + _gnome_init(NS_ConvertUTF16toUTF8(appName).get(), + "1.0", 1, empty, nullptr, 0, nullptr); } uint32_t iconSize = GetIconSize(aIconURI); @@ -386,9 +387,9 @@ nsIconChannel::InitWithGnome(nsIMozIconURI *aIconURI) } } - char* name = _gnome_icon_lookup(gIconTheme, NULL, spec.get(), NULL, &fileInfo, - type.get(), GNOME_ICON_LOOKUP_FLAGS_NONE, - NULL); + char* name = _gnome_icon_lookup(gIconTheme, nullptr, spec.get(), nullptr, + &fileInfo, type.get(), + GNOME_ICON_LOOKUP_FLAGS_NONE, nullptr); _gnome_vfs_file_info_clear(&fileInfo); if (!name) @@ -426,7 +427,7 @@ nsIconChannel::InitWithGnome(nsIMozIconURI *aIconURI) nsresult nsIconChannel::InitWithGIO(nsIMozIconURI *aIconURI) { - GIcon *icon = NULL; + GIcon *icon = nullptr; nsCOMPtr fileURI; // Read icon content @@ -441,7 +442,8 @@ nsIconChannel::InitWithGIO(nsIMozIconURI *aIconURI) GFile *file = g_file_new_for_uri(spec.get()); GFileInfo *fileInfo = g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_ICON, - G_FILE_QUERY_INFO_NONE, NULL, NULL); + G_FILE_QUERY_INFO_NONE, + nullptr, nullptr); g_object_unref(file); if (fileInfo) { // icon from g_content_type_get_icon doesn't need unref @@ -466,7 +468,7 @@ nsIconChannel::InitWithGIO(nsIMozIconURI *aIconURI) ms->GetTypeFromExtension(fileExt, type); } } - char *ctype = NULL; // character representation of content type + char *ctype = nullptr; // character representation of content type if (!type.IsEmpty()) { ctype = g_content_type_from_mime_type(type.get()); } @@ -478,7 +480,7 @@ nsIconChannel::InitWithGIO(nsIMozIconURI *aIconURI) // Get default icon theme GtkIconTheme *iconTheme = gtk_icon_theme_get_default(); - GtkIconInfo *iconInfo = NULL; + GtkIconInfo *iconInfo = nullptr; // Get icon size int32_t iconSize = GetIconSize(aIconURI); @@ -501,7 +503,7 @@ nsIconChannel::InitWithGIO(nsIMozIconURI *aIconURI) } // Create a GdkPixbuf buffer containing icon and scale it - GdkPixbuf* buf = gtk_icon_info_load_icon(iconInfo, NULL); + GdkPixbuf* buf = gtk_icon_info_load_icon(iconInfo, nullptr); gtk_icon_info_free(iconInfo); if (!buf) { return NS_ERROR_UNEXPECTED; @@ -593,7 +595,7 @@ nsIconChannel::Init(nsIURI* aURI) ensure_stock_image_widget(); GtkStyle *style = gtk_widget_get_style(gStockImageWidget); - GtkIconSet *icon_set = NULL; + GtkIconSet *icon_set = nullptr; if (!useIconName) { icon_set = gtk_style_lookup_icon_set(style, stockID.get()); } @@ -614,15 +616,15 @@ nsIconChannel::Init(nsIURI* aURI) } GdkPixbuf *icon = - gtk_icon_set_render_icon (icon_set, style, direction, state, - icon_size, gStockImageWidget, NULL); + gtk_icon_set_render_icon(icon_set, style, direction, state, + icon_size, gStockImageWidget, nullptr); if (useIconName) { gtk_icon_set_unref(icon_set); } // According to documentation, gtk_icon_set_render_icon() never returns - // NULL, but it does return NULL when we have the problem reported here: - // https://bugzilla.gnome.org/show_bug.cgi?id=629878#c13 + // nullptr, but it does return nullptr when we have the problem reported + // here: https://bugzilla.gnome.org/show_bug.cgi?id=629878#c13 if (!icon) return NS_ERROR_NOT_AVAILABLE; diff --git a/image/decoders/icon/nsIconModule.cpp b/image/decoders/icon/nsIconModule.cpp index 1e214a9d94e..4cf7c8f0d1d 100644 --- a/image/decoders/icon/nsIconModule.cpp +++ b/image/decoders/icon/nsIconModule.cpp @@ -22,17 +22,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIconProtocolHandler) NS_DEFINE_NAMED_CID(NS_ICONPROTOCOL_CID); static const mozilla::Module::CIDEntry kIconCIDs[] = { - { &kNS_ICONPROTOCOL_CID, false, NULL, nsIconProtocolHandlerConstructor }, - { NULL } + { &kNS_ICONPROTOCOL_CID, false, nullptr, nsIconProtocolHandlerConstructor }, + { nullptr } }; static const mozilla::Module::ContractIDEntry kIconContracts[] = { { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-icon", &kNS_ICONPROTOCOL_CID }, - { NULL } + { nullptr } }; static const mozilla::Module::CategoryEntry kIconCategories[] = { - { NULL } + { nullptr } }; static void @@ -48,8 +48,8 @@ static const mozilla::Module kIconModule = { kIconCIDs, kIconContracts, kIconCategories, - NULL, - NULL, + nullptr, + nullptr, IconDecoderModuleDtor }; diff --git a/image/decoders/icon/win/nsIconChannel.cpp b/image/decoders/icon/win/nsIconChannel.cpp index 836515554b3..64ed500516f 100644 --- a/image/decoders/icon/win/nsIconChannel.cpp +++ b/image/decoders/icon/win/nsIconChannel.cpp @@ -236,7 +236,7 @@ static DWORD GetSpecialFolderIcon(nsIFile* aFile, int aFolder, SHFILEINFOW* aSFI ::GetShortPathNameW(fileNativePathStr.get(), fileNativePath, ArrayLength(fileNativePath)); LPITEMIDLIST idList; - HRESULT hr = ::SHGetSpecialFolderLocation(NULL, aFolder, &idList); + HRESULT hr = ::SHGetSpecialFolderLocation(nullptr, aFolder, &idList); if (SUCCEEDED(hr)) { PRUnichar specialNativePath[MAX_PATH]; ::SHGetPathFromIDListW(idList, specialNativePath); @@ -456,7 +456,7 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, bool nonBlocki nsresult rv = NS_ERROR_NOT_AVAILABLE; // GetDIBits does not exist on windows mobile. - HICON hIcon = NULL; + HICON hIcon = nullptr; nsCOMPtr iconURI(do_QueryInterface(mUrl, &rv)); NS_ENSURE_SUCCESS(rv, rv); @@ -477,12 +477,12 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, bool nonBlocki if (GetIconInfo(hIcon, &iconInfo)) { // we got the bitmaps, first find out their size - HDC hDC = CreateCompatibleDC(NULL); // get a device context for the screen. + HDC hDC = CreateCompatibleDC(nullptr); // get a device context for the screen. BITMAPINFOHEADER maskHeader = {sizeof(BITMAPINFOHEADER)}; BITMAPINFOHEADER colorHeader = {sizeof(BITMAPINFOHEADER)}; int colorTableSize, maskTableSize; - if (GetDIBits(hDC, iconInfo.hbmMask, 0, 0, NULL, (BITMAPINFO*)&maskHeader, DIB_RGB_COLORS) && - GetDIBits(hDC, iconInfo.hbmColor, 0, 0, NULL, (BITMAPINFO*)&colorHeader, DIB_RGB_COLORS) && + if (GetDIBits(hDC, iconInfo.hbmMask, 0, 0, nullptr, (BITMAPINFO*)&maskHeader, DIB_RGB_COLORS) && + GetDIBits(hDC, iconInfo.hbmColor, 0, 0, nullptr, (BITMAPINFO*)&colorHeader, DIB_RGB_COLORS) && maskHeader.biHeight == colorHeader.biHeight && maskHeader.biWidth == colorHeader.biWidth && colorHeader.biBitCount > 8 && diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index 23003ea1708..1c0e30d283e 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -121,7 +121,7 @@ nsPNGDecoder::nsPNGDecoder(RasterImage &aImage) nsPNGDecoder::~nsPNGDecoder() { if (mPNG) - png_destroy_read_struct(&mPNG, mInfo ? &mInfo : NULL, NULL); + png_destroy_read_struct(&mPNG, mInfo ? &mInfo : nullptr, nullptr); if (mCMSLine) nsMemory::Free(mCMSLine); if (interlacebuf) @@ -237,7 +237,7 @@ nsPNGDecoder::InitInternal() /* Always decode to 24 bit pixdepth */ mPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, - NULL, nsPNGDecoder::error_callback, + nullptr, nsPNGDecoder::error_callback, nsPNGDecoder::warning_callback); if (!mPNG) { PostDecoderError(NS_ERROR_OUT_OF_MEMORY); @@ -247,7 +247,7 @@ nsPNGDecoder::InitInternal() mInfo = png_create_info_struct(mPNG); if (!mInfo) { PostDecoderError(NS_ERROR_OUT_OF_MEMORY); - png_destroy_read_struct(&mPNG, NULL, NULL); + png_destroy_read_struct(&mPNG, nullptr, nullptr); return; } @@ -348,7 +348,7 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount) if (!HasError()) PostDataError(); - png_destroy_read_struct(&mPNG, &mInfo, NULL); + png_destroy_read_struct(&mPNG, &mInfo, nullptr); return; } @@ -498,7 +498,7 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) int bit_depth, color_type, interlace_type, compression_type, filter_type; unsigned int channels; - png_bytep trans = NULL; + png_bytep trans = nullptr; int num_trans = 0; nsPNGDecoder *decoder = @@ -633,7 +633,8 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) #ifdef PNG_APNG_SUPPORTED if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) - png_set_progressive_frame_fn(png_ptr, nsPNGDecoder::frame_info_callback, NULL); + png_set_progressive_frame_fn(png_ptr, nsPNGDecoder::frame_info_callback, + nullptr); if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) { decoder->mFrameIsHidden = true; @@ -680,14 +681,14 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row, * image is interlacing, and you turned on the interlace handler, * this function will be called for every row in every pass. * Some of these rows will not be changed from the previous pass. - * When the row is not changed, the new_row variable will be NULL. - * The rows and passes are called in order, so you don't really - * need the row_num and pass, but I'm supplying them because it - * may make your life easier. + * When the row is not changed, the new_row variable will be + * nullptr. The rows and passes are called in order, so you don't + * really need the row_num and pass, but I'm supplying them + * because it may make your life easier. * - * For the non-NULL rows of interlaced images, you must call + * For the non-nullptr rows of interlaced images, you must call * png_progressive_combine_row() passing in the row and the - * old row. You can call this function for NULL rows (it will + * old row. You can call this function for nullptr rows (it will * just return) and for non-interlaced images (it just does the * memcpy for you) if it will make the code easier. Thus, you * can just do this for all cases: diff --git a/image/decoders/nsPNGDecoder.h b/image/decoders/nsPNGDecoder.h index 51f2ebd212f..9ba218500f6 100644 --- a/image/decoders/nsPNGDecoder.h +++ b/image/decoders/nsPNGDecoder.h @@ -57,7 +57,7 @@ public: png_color_type; if (png_get_IHDR(mPNG, mInfo, &png_width, &png_height, &png_bit_depth, - &png_color_type, NULL, NULL, NULL)) { + &png_color_type, nullptr, nullptr, nullptr)) { return ((png_color_type == PNG_COLOR_TYPE_RGB_ALPHA || png_color_type == PNG_COLOR_TYPE_RGB) && diff --git a/image/src/DiscardTracker.cpp b/image/src/DiscardTracker.cpp index 3009cf62648..c0708b4bf5a 100644 --- a/image/src/DiscardTracker.cpp +++ b/image/src/DiscardTracker.cpp @@ -22,7 +22,7 @@ static const char* sDiscardTimeoutPref = "image.mem.min_discard_timeout_ms"; /* static */ int64_t DiscardTracker::sCurrentDecodedImageBytes = 0; /* static */ uint32_t DiscardTracker::sMinDiscardTimeoutMs = 10000; /* static */ uint32_t DiscardTracker::sMaxDecodedImageKB = 42 * 1024; -/* static */ PRLock * DiscardTracker::sAllocationLock = NULL; +/* static */ PRLock * DiscardTracker::sAllocationLock = nullptr; /* * When we notice we're using too much memory for decoded images, we enqueue a @@ -100,7 +100,7 @@ DiscardTracker::Shutdown() if (sTimer) { sTimer->Cancel(); - sTimer = NULL; + sTimer = nullptr; } // Clear the sDiscardableImages linked list so that its destructor diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 06b3900e785..e592fa5bc61 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -1052,14 +1052,14 @@ size_t RasterImage::NonHeapSizeOfDecoded() const { return SizeOfDecodedWithComputedFallbackIfHeap(gfxASurface::MEMORY_IN_PROCESS_NONHEAP, - NULL); + nullptr); } size_t RasterImage::OutOfProcessSizeOfDecoded() const { return SizeOfDecodedWithComputedFallbackIfHeap(gfxASurface::MEMORY_OUT_OF_PROCESS, - NULL); + nullptr); } void diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index 52533036380..c4490832465 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -840,7 +840,7 @@ size_t imgFrame::SizeOfExcludingThisWithComputedFallbackIfHeap(gfxASurface::MemoryLocation aLocation, mozilla::MallocSizeOf aMallocSizeOf) const { // aMallocSizeOf is only used if aLocation==MEMORY_IN_PROCESS_HEAP. It - // should be NULL otherwise. + // should be nullptr otherwise. NS_ABORT_IF_FALSE( (aLocation == gfxASurface::MEMORY_IN_PROCESS_HEAP && aMallocSizeOf) || (aLocation != gfxASurface::MEMORY_IN_PROCESS_HEAP && !aMallocSizeOf), diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp index c743e099b7d..89290b2ad1a 100644 --- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -449,9 +449,9 @@ static nsresult NewImageChannel(nsIChannel **aResult, aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); } - // Pass in a NULL loadgroup because this is the underlying network request. - // This request may be referenced by several proxy image requests (psossibly - // in different documents). + // Pass in a nullptr loadgroup because this is the underlying network + // request. This request may be referenced by several proxy image requests + // (possibly in different documents). // If all of the proxy requests are canceled then this request should be // canceled too. // @@ -1638,7 +1638,7 @@ nsresult imgLoader::LoadImage(nsIURI *aURI, entry->Touch(); #ifdef DEBUG_joe - printf("CACHEGET: %d %s %d\n", time(NULL), spec.get(), entry->SizeOfData()); + printf("CACHEGET: %d %s %d\n", time(nullptr), spec.get(), entry->SizeOfData()); #endif } else { @@ -1991,7 +1991,7 @@ nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, uint32_t aLeng /* or how about ART? */ /* ART begins with JG (4A 47). Major version offset 2. - * Minor version offset 3. Offset 4 must be NULL. + * Minor version offset 3. Offset 4 must be nullptr. */ else if (aLength >= 5 && ((unsigned char) aContents[0])==0x4a && From 8d67bc95f25d1294501d338f6a3626f946b0c4eb Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Fri, 23 Aug 2013 15:51:15 -0400 Subject: [PATCH 02/87] Bug 784739 - Switch from NULL to nullptr in hal/. r=ehsan --- hal/Hal.cpp | 8 ++++---- hal/cocoa/CocoaGamepad.cpp | 32 ++++++++++++++++---------------- hal/gonk/GonkFMRadio.cpp | 8 ++++---- hal/gonk/GonkHal.cpp | 26 ++++++++++++++------------ hal/gonk/GonkSensor.cpp | 4 ++-- hal/gonk/GonkSwitch.cpp | 2 +- hal/gonk/UeventPoller.cpp | 2 +- hal/linux/LinuxGamepad.cpp | 4 +++- hal/windows/WindowsSensor.cpp | 10 ++++++---- 9 files changed, 51 insertions(+), 45 deletions(-) diff --git a/hal/Hal.cpp b/hal/Hal.cpp index b4138159be2..a05699eea12 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -217,7 +217,7 @@ public: } void BroadcastInformation(const InfoType& aInfo) { - // It is possible for mObservers to be NULL here on some platforms, + // It is possible for mObservers to be nullptr here on some platforms, // because a call to BroadcastInformation gets queued up asynchronously // while RemoveObserver is running (and before the notifications are // disabled). The queued call can then get run after mObservers has @@ -746,12 +746,12 @@ SwitchState GetCurrentSwitchState(SwitchDevice aDevice) typedef mozilla::ObserverList SwitchObserverList; -static SwitchObserverList *sSwitchObserverLists = NULL; +static SwitchObserverList *sSwitchObserverLists = nullptr; static SwitchObserverList& GetSwitchObserverList(SwitchDevice aDevice) { MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE); - if (sSwitchObserverLists == NULL) { + if (sSwitchObserverLists == nullptr) { sSwitchObserverLists = new SwitchObserverList[NUM_SWITCH_DEVICE]; } return sSwitchObserverLists[aDevice]; @@ -766,7 +766,7 @@ ReleaseObserversIfNeeded() { //The length of every list is 0, no observer in the list. delete [] sSwitchObserverLists; - sSwitchObserverLists = NULL; + sSwitchObserverLists = nullptr; } void diff --git a/hal/cocoa/CocoaGamepad.cpp b/hal/cocoa/CocoaGamepad.cpp index bcd7960964f..a2f74fcdc89 100644 --- a/hal/cocoa/CocoaGamepad.cpp +++ b/hal/cocoa/CocoaGamepad.cpp @@ -49,11 +49,11 @@ class Gamepad { vector axes; public: - Gamepad() : mDevice(NULL), mSuperIndex(-1) {} + Gamepad() : mDevice(nullptr), mSuperIndex(-1) {} bool operator==(IOHIDDeviceRef device) const { return mDevice == device; } - bool empty() const { return mDevice == NULL; } + bool empty() const { return mDevice == nullptr; } void clear() { - mDevice = NULL; + mDevice = nullptr; buttons.clear(); axes.clear(); mSuperIndex = -1; @@ -70,7 +70,7 @@ class Gamepad { if (buttons[i].element == element) return &buttons[i]; } - return NULL; + return nullptr; } const Axis* lookupAxis(IOHIDElementRef element) const { @@ -78,7 +78,7 @@ class Gamepad { if (axes[i].element == element) return &axes[i]; } - return NULL; + return nullptr; } }; @@ -87,7 +87,7 @@ void Gamepad::init(IOHIDDeviceRef device) { mDevice = device; CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, - NULL, + nullptr, kIOHIDOptionsTypeNone); CFIndex n = CFArrayGetCount(elements); for (CFIndex i = 0; i < n; i++) { @@ -247,13 +247,13 @@ MatchingDictionary(UInt32 inUsagePage, UInt32 inUsage) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!dict) - return NULL; + return nullptr; CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &inUsagePage); if (!number) { CFRelease(dict); - return NULL; + return nullptr; } CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number); CFRelease(number); @@ -261,7 +261,7 @@ MatchingDictionary(UInt32 inUsagePage, UInt32 inUsage) number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &inUsage); if (!number) { CFRelease(dict); - return NULL; + return nullptr; } CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number); CFRelease(number); @@ -269,17 +269,17 @@ MatchingDictionary(UInt32 inUsagePage, UInt32 inUsage) return dict; } -DarwinGamepadService::DarwinGamepadService() : mManager(NULL) {} +DarwinGamepadService::DarwinGamepadService() : mManager(nullptr) {} DarwinGamepadService::~DarwinGamepadService() { - if (mManager != NULL) + if (mManager != nullptr) CFRelease(mManager); } void DarwinGamepadService::Startup() { - if (mManager != NULL) + if (mManager != nullptr) return; IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, @@ -302,7 +302,7 @@ void DarwinGamepadService::Startup() } CFArrayRef criteria = - CFArrayCreate(kCFAllocatorDefault, (const void**)criteria_arr, 2, NULL); + CFArrayCreate(kCFAllocatorDefault, (const void**)criteria_arr, 2, nullptr); if (!criteria) { CFRelease(criteria_arr[1]); CFRelease(criteria_arr[0]); @@ -342,7 +342,7 @@ void DarwinGamepadService::Shutdown() if (manager) { IOHIDManagerClose(manager, 0); CFRelease(manager); - mManager = NULL; + mManager = nullptr; } } @@ -351,7 +351,7 @@ void DarwinGamepadService::Shutdown() namespace mozilla { namespace hal_impl { -DarwinGamepadService* gService = NULL; +DarwinGamepadService* gService = nullptr; void StartMonitoringGamepadStatus() { @@ -369,7 +369,7 @@ void StopMonitoringGamepadStatus() gService->Shutdown(); delete gService; - gService = NULL; + gService = nullptr; } } // namespace hal_impl diff --git a/hal/gonk/GonkFMRadio.cpp b/hal/gonk/GonkFMRadio.cpp index 48b8dede5ed..01602dc4b3f 100644 --- a/hal/gonk/GonkFMRadio.cpp +++ b/hal/gonk/GonkFMRadio.cpp @@ -203,7 +203,7 @@ runTavaruaRadio(void *) if (!sRadioEnabled) { NS_DispatchToMainThread(new RadioUpdate(hal::FM_RADIO_OPERATION_ENABLE, hal::FM_RADIO_OPERATION_STATUS_FAIL)); - return NULL; + return nullptr; } uint8_t buf[128]; @@ -240,7 +240,7 @@ runTavaruaRadio(void *) } } - return NULL; + return nullptr; } /* This runs on the main thread but most of the @@ -282,7 +282,7 @@ EnableFMRadio(const hal::FMRadioSettings& aInfo) // Tavarua specific start sTavaruaVersion = cap.version; - pthread_create(&sRadioThread, NULL, runTavaruaRadio, NULL); + pthread_create(&sRadioThread, nullptr, runTavaruaRadio, nullptr); // Tavarua specific end } @@ -301,7 +301,7 @@ DisableFMRadio() } // Tavarua specific end - pthread_join(sRadioThread, NULL); + pthread_join(sRadioThread, nullptr); close(sRadioFD); diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp index 45a639f57f4..d69babd21fa 100644 --- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -183,7 +183,7 @@ VibratorRunnable::Run() mMonitor.Wait(); } } - sVibratorRunnable = NULL; + sVibratorRunnable = nullptr; return NS_OK; } @@ -345,7 +345,7 @@ UnregisterBatteryObserverIOThread() MOZ_ASSERT(sBatteryObserver); UnregisterUeventListener(sBatteryObserver); - sBatteryObserver = NULL; + sBatteryObserver = nullptr; } void @@ -593,7 +593,7 @@ SetCpuSleepAllowed(bool aAllowed) UpdateCpuSleepState(); } -static light_device_t* sLights[hal::eHalLightID_Count]; // will be initialized to NULL +static light_device_t* sLights[hal::eHalLightID_Count]; // will be initialized to nullptr light_device_t* GetDevice(hw_module_t* module, char const* name) { @@ -603,14 +603,14 @@ light_device_t* GetDevice(hw_module_t* module, char const* name) if (err == 0) { return (light_device_t*)device; } else { - return NULL; + return nullptr; } } void InitLights() { - // assume that if backlight is NULL, nothing has been set yet + // assume that if backlight is nullptr, nothing has been set yet // if this is not true, the initialization will occur everytime a light is read or set! if (!sLights[hal::eHalLightID_Backlight]) { int err; @@ -651,7 +651,8 @@ SetLight(hal::LightType light, const hal::LightConfiguration& aConfig) InitLights(); - if (light < 0 || light >= hal::eHalLightID_Count || sLights[light] == NULL) { + if (light < 0 || light >= hal::eHalLightID_Count || + sLights[light] == nullptr) { return false; } @@ -676,7 +677,8 @@ GetLight(hal::LightType light, hal::LightConfiguration* aConfig) InitLights(); #endif - if (light < 0 || light >= hal::eHalLightID_Count || sLights[light] == NULL) { + if (light < 0 || light >= hal::eHalLightID_Count || + sLights[light] == nullptr) { return false; } @@ -848,7 +850,7 @@ public: int AlarmData::sNextGeneration = 0; -AlarmData* sAlarmData = NULL; +AlarmData* sAlarmData = nullptr; class AlarmFiredEvent : public nsRunnable { public: @@ -920,7 +922,7 @@ WaitForAlarm(void* aData) } pthread_cleanup_pop(1); - return NULL; + return nullptr; } bool @@ -941,7 +943,7 @@ EnableAlarm() sigemptyset(&actions.sa_mask); actions.sa_flags = 0; actions.sa_handler = ShutDownAlarm; - if (sigaction(SIGUSR1, &actions, NULL)) { + if (sigaction(SIGUSR1, &actions, nullptr)) { HAL_LOG(("Failed to set SIGUSR1 signal for alarm-watcher thread.")); return false; } @@ -956,7 +958,7 @@ EnableAlarm() int status = pthread_create(&sAlarmFireWatcherThread, &attr, WaitForAlarm, alarmData.get()); if (status) { - alarmData = NULL; + alarmData = nullptr; delete sInternalLockCpuMonitor; HAL_LOG(("Failed to create alarm-watcher thread. Status: %d.", status)); return false; @@ -975,7 +977,7 @@ DisableAlarm() MOZ_ASSERT(sAlarmData); // NB: this must happen-before the thread cancellation. - sAlarmData = NULL; + sAlarmData = nullptr; // The cancel will interrupt the thread and destroy it, freeing the // data pointed at by sAlarmData. diff --git a/hal/gonk/GonkSensor.cpp b/hal/gonk/GonkSensor.cpp index 6bb86aee59b..710c06e07b5 100644 --- a/hal/gonk/GonkSensor.cpp +++ b/hal/gonk/GonkSensor.cpp @@ -229,7 +229,7 @@ static void SetSensorState(SensorType aSensor, bool activate) { int type = HalSensorToHardwareSensor(aSensor); - const sensor_t* sensors = NULL; + const sensor_t* sensors = nullptr; int size = sSensorModule->get_sensors_list(sSensorModule, &sensors); for (ssize_t i = 0; i < size; i++) { @@ -253,7 +253,7 @@ EnableSensorNotifications(SensorType aSensor) sensors_open(&sSensorModule->common, &sSensorDevice); if (!sSensorDevice) { - sSensorModule = NULL; + sSensorModule = nullptr; LOGE("Can't get sensor poll device from module \n"); return; } diff --git a/hal/gonk/GonkSwitch.cpp b/hal/gonk/GonkSwitch.cpp index 617a0ef2a5e..da421813ae9 100644 --- a/hal/gonk/GonkSwitch.cpp +++ b/hal/gonk/GonkSwitch.cpp @@ -359,7 +359,7 @@ ReleaseResourceIfNeed() { if (sSwitchObserver->GetEnableCount() == 0) { UnregisterUeventListener(sSwitchObserver); - sSwitchObserver = NULL; + sSwitchObserver = nullptr; } } diff --git a/hal/gonk/UeventPoller.cpp b/hal/gonk/UeventPoller.cpp index 2c83cbd56f7..b55e8b8df0c 100644 --- a/hal/gonk/UeventPoller.cpp +++ b/hal/gonk/UeventPoller.cpp @@ -183,7 +183,7 @@ InitializeUevent() static void ShutdownUevent() { - sPoller = NULL; + sPoller = nullptr; } void diff --git a/hal/linux/LinuxGamepad.cpp b/hal/linux/LinuxGamepad.cpp index edcc38b8a35..f0132b58c80 100644 --- a/hal/linux/LinuxGamepad.cpp +++ b/hal/linux/LinuxGamepad.cpp @@ -120,7 +120,9 @@ LinuxGamepadService::AddDevice(struct udev_device* dev) mUdev.udev_device_get_property_value(dev, "ID_MODEL_ID"); if (!vendor_id || !model_id) { struct udev_device* parent = - mUdev.udev_device_get_parent_with_subsystem_devtype(dev, "input", NULL); + mUdev.udev_device_get_parent_with_subsystem_devtype(dev, + "input", + nullptr); if (parent) { vendor_id = mUdev.udev_device_get_sysattr_value(parent, "id/vendor"); model_id = mUdev.udev_device_get_sysattr_value(parent, "id/product"); diff --git a/hal/windows/WindowsSensor.cpp b/hal/windows/WindowsSensor.cpp index 10185f5da74..d727565b2bb 100644 --- a/hal/windows/WindowsSensor.cpp +++ b/hal/windows/WindowsSensor.cpp @@ -115,8 +115,10 @@ EnableSensorNotifications(SensorType aSensor) } nsRefPtr manager; - if (FAILED(CoCreateInstance(CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, - IID_ISensorManager, getter_AddRefs(manager)))) { + if (FAILED(CoCreateInstance(CLSID_SensorManager, nullptr, + CLSCTX_INPROC_SERVER, + IID_ISensorManager, + getter_AddRefs(manager)))) { return; } @@ -143,7 +145,7 @@ EnableSensorNotifications(SensorType aSensor) // Set report interval to 100ms if possible. // Default value depends on drivers. nsRefPtr values; - if (SUCCEEDED(CoCreateInstance(CLSID_PortableDeviceValues, NULL, + if (SUCCEEDED(CoCreateInstance(CLSID_PortableDeviceValues, nullptr, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, getter_AddRefs(values)))) { @@ -173,7 +175,7 @@ void DisableSensorNotifications(SensorType aSensor) { if (aSensor == SENSOR_ACCELERATION && sAccelerometer) { - sAccelerometer->SetEventSink(NULL); + sAccelerometer->SetEventSink(nullptr); sAccelerometer = nullptr; } } From 3a1d90cf4e8691235b43245c618e90533710925b Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Fri, 23 Aug 2013 15:51:30 -0400 Subject: [PATCH 03/87] Bug 784739 - Switch from NULL to nullptr in intl/. r=ehsan --- intl/locale/src/mac/nsCollationMacUC.cpp | 8 ++++---- intl/locale/src/mac/nsDateTimeFormatMac.cpp | 16 ++++++++++------ intl/locale/src/nsLocaleService.cpp | 2 +- intl/locale/src/os2/nsCollationOS2.cpp | 9 ++++++--- intl/locale/src/os2/nsDateTimeFormatOS2.cpp | 2 +- intl/locale/src/os2/nsOS2Locale.cpp | 2 +- intl/locale/src/windows/nsCollationWin.cpp | 2 +- intl/locale/src/windows/nsDateTimeFormatWin.cpp | 8 ++++---- intl/lwbrk/src/nsCarbonBreaker.cpp | 5 ++++- intl/lwbrk/src/nsUniscribeBreaker.cpp | 3 ++- 10 files changed, 34 insertions(+), 23 deletions(-) diff --git a/intl/locale/src/mac/nsCollationMacUC.cpp b/intl/locale/src/mac/nsCollationMacUC.cpp index 97c353fc1ba..46c1a1d98b2 100644 --- a/intl/locale/src/mac/nsCollationMacUC.cpp +++ b/intl/locale/src/mac/nsCollationMacUC.cpp @@ -13,9 +13,9 @@ NS_IMPL_ISUPPORTS1(nsCollationMacUC, nsICollation) nsCollationMacUC::nsCollationMacUC() : mInit(false) , mHasCollator(false) - , mLocale(NULL) + , mLocale(nullptr) , mLastStrength(-1) - , mCollator(NULL) + , mCollator(nullptr) , mBuffer(nullptr) , mBufferLen(1) { @@ -174,7 +174,7 @@ NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& err = ::UCCompareText(mCollator, (const UniChar *) PromiseFlatString(string1).get(), (UniCharCount) string1.Length(), (const UniChar *) PromiseFlatString(string2).get(), (UniCharCount) string2.Length(), - NULL, (SInt32*) result); + nullptr, (SInt32*) result); NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE); return NS_OK; @@ -193,7 +193,7 @@ NS_IMETHODIMP nsCollationMacUC::CompareRawSortKey(const uint8_t* key1, uint32_t OSStatus err; err = ::UCCompareCollationKeys((const UCCollationValue*) key1, (ItemCount) len1, (const UCCollationValue*) key2, (ItemCount) len2, - NULL, (SInt32*) result); + nullptr, (SInt32*) result); NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE); diff --git a/intl/locale/src/mac/nsDateTimeFormatMac.cpp b/intl/locale/src/mac/nsDateTimeFormatMac.cpp index dc4b526cc09..585cc937c03 100644 --- a/intl/locale/src/mac/nsDateTimeFormatMac.cpp +++ b/intl/locale/src/mac/nsDateTimeFormatMac.cpp @@ -113,8 +113,10 @@ nsresult nsDateTimeFormatMac::FormatTMTime(nsILocale* locale, if (!locale) { formatterLocale = CFLocaleCopyCurrent(); } else { - CFStringRef localeStr = CFStringCreateWithCharacters(NULL, mLocale.get(), mLocale.Length()); - formatterLocale = CFLocaleCreate(NULL, localeStr); + CFStringRef localeStr = CFStringCreateWithCharacters(nullptr, + mLocale.get(), + mLocale.Length()); + formatterLocale = CFLocaleCreate(nullptr, localeStr); CFRelease(localeStr); } @@ -162,7 +164,7 @@ nsresult nsDateTimeFormatMac::FormatTMTime(nsILocale* locale, // Create the formatter and fix up its formatting as necessary: CFDateFormatterRef formatter = - CFDateFormatterCreate(NULL, formatterLocale, dateStyle, timeStyle); + CFDateFormatterCreate(nullptr, formatterLocale, dateStyle, timeStyle); CFRelease(formatterLocale); @@ -172,7 +174,7 @@ nsresult nsDateTimeFormatMac::FormatTMTime(nsILocale* locale, dateFormatSelector == kDateFormatYearMonth ? CFSTR("yyyy/MM ") : CFSTR("EEE "); CFStringRef oldFormat = CFDateFormatterGetFormat(formatter); - CFMutableStringRef newFormat = CFStringCreateMutableCopy(NULL, 0, oldFormat); + CFMutableStringRef newFormat = CFStringCreateMutableCopy(nullptr, 0, oldFormat); CFStringInsert(newFormat, 0, dateFormat); CFDateFormatterSetFormat(formatter, newFormat); CFRelease(newFormat); // note we don't own oldFormat @@ -182,7 +184,7 @@ nsresult nsDateTimeFormatMac::FormatTMTime(nsILocale* locale, timeFormatSelector == kTimeFormatNoSecondsForce24Hour) { // Replace "h" with "H", and remove "a": CFStringRef oldFormat = CFDateFormatterGetFormat(formatter); - CFMutableStringRef newFormat = CFStringCreateMutableCopy(NULL, 0, oldFormat); + CFMutableStringRef newFormat = CFStringCreateMutableCopy(nullptr, 0, oldFormat); CFIndex replaceCount = CFStringFindAndReplace(newFormat, CFSTR("h"), CFSTR("H"), CFRangeMake(0, CFStringGetLength(newFormat)), @@ -210,7 +212,9 @@ nsresult nsDateTimeFormatMac::FormatTMTime(nsILocale* locale, CFAbsoluteTime absTime = CFGregorianDateGetAbsoluteTime(date, timeZone); CFRelease(timeZone); - CFStringRef formattedDate = CFDateFormatterCreateStringWithAbsoluteTime(NULL, formatter, absTime); + CFStringRef formattedDate = CFDateFormatterCreateStringWithAbsoluteTime(nullptr, + formatter, + absTime); CFIndex stringLen = CFStringGetLength(formattedDate); diff --git a/intl/locale/src/nsLocaleService.cpp b/intl/locale/src/nsLocaleService.cpp index 12715552804..b302b41d21a 100644 --- a/intl/locale/src/nsLocaleService.cpp +++ b/intl/locale/src/nsLocaleService.cpp @@ -176,7 +176,7 @@ nsLocaleService::nsLocaleService(void) nsRefPtr resultLocale(new nsLocale()); - LocaleObject locale_object = NULL; + LocaleObject locale_object = nullptr; int result = UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"", &locale_object); if (result != ULS_SUCCESS) { diff --git a/intl/locale/src/os2/nsCollationOS2.cpp b/intl/locale/src/os2/nsCollationOS2.cpp index f020fa7a0fc..da8cc1ac5eb 100644 --- a/intl/locale/src/os2/nsCollationOS2.cpp +++ b/intl/locale/src/os2/nsCollationOS2.cpp @@ -71,7 +71,7 @@ nsresult nsCollationOS2::CompareString(int32_t strength, stringNormalized2 = string2; } - LocaleObject locObj = NULL; + LocaleObject locObj = nullptr; int ret = UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"", &locObj); if (ret != ULS_SUCCESS) UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"C", &locObj); @@ -98,13 +98,16 @@ nsresult nsCollationOS2::AllocateRawSortKey(int32_t strength, stringNormalized = stringIn; } - LocaleObject locObj = NULL; + LocaleObject locObj = nullptr; int ret = UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"", &locObj); if (ret != ULS_SUCCESS) UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"C", &locObj); res = NS_ERROR_FAILURE; // From here on out assume failure... - int length = UniStrxfrm(locObj, NULL, reinterpret_cast(stringNormalized.get()),0); + int length = UniStrxfrm(locObj, + nullptr, + reinterpret_cast(stringNormalized.get()), + 0); if (length >= 0) { length += 5; // Allow for the "extra" chars UniStrxfrm() // will out put (overrunning the buffer if diff --git a/intl/locale/src/os2/nsDateTimeFormatOS2.cpp b/intl/locale/src/os2/nsDateTimeFormatOS2.cpp index b3cc5584c73..d5bfe91e951 100644 --- a/intl/locale/src/os2/nsDateTimeFormatOS2.cpp +++ b/intl/locale/src/os2/nsDateTimeFormatOS2.cpp @@ -34,7 +34,7 @@ nsresult nsDateTimeFormatOS2::FormatTMTime(nsILocale* locale, UniChar uFmtD[NSDATETIME_FORMAT_BUFFER_LEN] = { 0 }; UniChar uFmtT[NSDATETIME_FORMAT_BUFFER_LEN] = { 0 }; UniChar *pString = nullptr; - LocaleObject locObj = NULL; + LocaleObject locObj = nullptr; int ret = UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"", &locObj); if (ret != ULS_SUCCESS) UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"C", &locObj); diff --git a/intl/locale/src/os2/nsOS2Locale.cpp b/intl/locale/src/os2/nsOS2Locale.cpp index 28c3a267f9d..3ca7ed6400a 100644 --- a/intl/locale/src/os2/nsOS2Locale.cpp +++ b/intl/locale/src/os2/nsOS2Locale.cpp @@ -52,7 +52,7 @@ nsOS2Locale::~nsOS2Locale(void) NS_IMETHODIMP nsOS2Locale::GetPlatformLocale(const nsAString& locale, PULONG os2Codepage) { - LocaleObject locObj = NULL; + LocaleObject locObj = nullptr; int codePage; nsAutoString tempLocale(locale); tempLocale.ReplaceChar('-', '_'); diff --git a/intl/locale/src/windows/nsCollationWin.cpp b/intl/locale/src/windows/nsCollationWin.cpp index 8114a0bf43a..45b64ff4b0c 100644 --- a/intl/locale/src/windows/nsCollationWin.cpp +++ b/intl/locale/src/windows/nsCollationWin.cpp @@ -125,7 +125,7 @@ nsresult nsCollationWin::AllocateRawSortKey(int32_t strength, byteLen = LCMapStringW(mLCID, dwMapFlags, (LPCWSTR) PromiseFlatString(stringIn).get(), - -1, NULL, 0); + -1, nullptr, 0); buffer = PR_Malloc(byteLen); if (!buffer) { res = NS_ERROR_OUT_OF_MEMORY; diff --git a/intl/locale/src/windows/nsDateTimeFormatWin.cpp b/intl/locale/src/windows/nsDateTimeFormatWin.cpp index 44ddb7d1ec1..adae99c0cd4 100644 --- a/intl/locale/src/windows/nsDateTimeFormatWin.cpp +++ b/intl/locale/src/windows/nsDateTimeFormatWin.cpp @@ -155,7 +155,7 @@ nsresult nsDateTimeFormatWin::FormatTMTime(nsILocale* locale, dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN); } else { - dateLen = nsGetDateFormatW(dwFlags_Date, &system_time, NULL, + dateLen = nsGetDateFormatW(dwFlags_Date, &system_time, nullptr, dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN); } if (dateLen != 0) { @@ -168,7 +168,7 @@ nsresult nsDateTimeFormatWin::FormatTMTime(nsILocale* locale, timeLen = 0; } else { - timeLen = nsGetTimeFormatW(dwFlags_Time, &system_time, NULL, + timeLen = nsGetTimeFormatW(dwFlags_Time, &system_time, nullptr, timeBuffer, NSDATETIMEFORMAT_BUFFER_LEN); if (timeLen != 0) { timeLen--; // Since the count includes the terminating null. @@ -239,7 +239,7 @@ int nsDateTimeFormatWin::nsGetTimeFormatW(DWORD dwFlags, const SYSTEMTIME *lpTim format ? const_cast (NS_ConvertASCIItoUTF16(format).get()) : - NULL, + nullptr, (LPWSTR) timeStr, cchTime); return len; } @@ -252,7 +252,7 @@ int nsDateTimeFormatWin::nsGetDateFormatW(DWORD dwFlags, const SYSTEMTIME *lpDat format ? const_cast (NS_ConvertASCIItoUTF16(format).get()) : - NULL, + nullptr, (LPWSTR) dateStr, cchDate); return len; } diff --git a/intl/lwbrk/src/nsCarbonBreaker.cpp b/intl/lwbrk/src/nsCarbonBreaker.cpp index 725231c3354..fa3aa2f2982 100644 --- a/intl/lwbrk/src/nsCarbonBreaker.cpp +++ b/intl/lwbrk/src/nsCarbonBreaker.cpp @@ -15,7 +15,10 @@ NS_GetComplexLineBreaks(const PRUnichar* aText, uint32_t aLength, memset(aBreakBefore, false, aLength * sizeof(uint8_t)); - OSStatus status = UCCreateTextBreakLocator(NULL, 0, kUCTextBreakLineMask, &breakLocator); + OSStatus status = UCCreateTextBreakLocator(nullptr, + 0, + kUCTextBreakLineMask, + &breakLocator); if (status != noErr) return; diff --git a/intl/lwbrk/src/nsUniscribeBreaker.cpp b/intl/lwbrk/src/nsUniscribeBreaker.cpp index 6e53e8956eb..04dacdb262a 100644 --- a/intl/lwbrk/src/nsUniscribeBreaker.cpp +++ b/intl/lwbrk/src/nsUniscribeBreaker.cpp @@ -29,7 +29,8 @@ NS_GetComplexLineBreaks(const PRUnichar* aText, uint32_t aLength, return; do { - result = ScriptItemize(aText, aLength, items.Length(), NULL, NULL, items.Elements(), &outItems); + result = ScriptItemize(aText, aLength, items.Length(), nullptr, nullptr, + items.Elements(), &outItems); if (result == E_OUTOFMEMORY) { if (!items.AppendElements(items.Length())) From ee5104f639d3d974cef4e00aad883fc517630e65 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Fri, 23 Aug 2013 15:51:44 -0400 Subject: [PATCH 04/87] Bug 784739 - Switch from NULL to nullptr in ipc/. r=ehsan --- ipc/app/MozillaRuntimeMain.cpp | 2 +- ipc/dbus/DBusUtils.cpp | 16 ++++++++-------- ipc/dbus/DBusUtils.h | 2 +- ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp | 4 ++-- ipc/ipdl/test/cxx/TestCrashCleanup.cpp | 4 ++-- ipc/ipdl/test/cxx/TestDataStructures.cpp | 2 +- ipc/ipdl/test/cxx/TestFailedCtor.h | 2 +- ipc/ipdl/test/cxx/TestRPCErrorCleanup.cpp | 4 ++-- ipc/ipdl/test/cxx/TestRPCShutdownRace.cpp | 4 ++-- ipc/testshell/TestShellParent.h | 2 +- ipc/testshell/XPCShellEnvironment.cpp | 10 +++++----- 11 files changed, 26 insertions(+), 26 deletions(-) diff --git a/ipc/app/MozillaRuntimeMain.cpp b/ipc/app/MozillaRuntimeMain.cpp index 09c2609ca8a..ef4d6f7f220 100644 --- a/ipc/app/MozillaRuntimeMain.cpp +++ b/ipc/app/MozillaRuntimeMain.cpp @@ -63,7 +63,7 @@ main(int argc, char* argv[]) #endif #if defined(XP_WIN) && defined(DEBUG_bent) - MessageBox(NULL, L"Hi", L"Hi", MB_OK); + MessageBox(nullptr, L"Hi", L"Hi", MB_OK); #endif // Check for the absolute minimum number of args we need to move diff --git a/ipc/dbus/DBusUtils.cpp b/ipc/dbus/DBusUtils.cpp index 5a81e1d6b3f..819bcf56db8 100644 --- a/ipc/dbus/DBusUtils.cpp +++ b/ipc/dbus/DBusUtils.cpp @@ -359,11 +359,11 @@ static dbus_bool_t dbus_func_args_async_valist(DBusConnection *conn, const char *func, int first_arg_type, va_list args) { - DBusMessage *msg = NULL; + DBusMessage *msg = nullptr; /* Compose the command */ msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func); - if (msg == NULL) { + if (msg == nullptr) { LOG("Could not allocate D-Bus message object!"); goto done; } @@ -524,12 +524,12 @@ dbus_func_send_and_block(DBusConnection* aConnection, return TRUE; } -// If err is NULL, then any errors will be LOG'd, and free'd and the reply -// will be NULL. -// If err is not NULL, then it is assumed that dbus_error_init was already +// If err is nullptr, then any errors will be LOG'd, and free'd and the reply +// will be nullptr. +// If err is not nullptr, then it is assumed that dbus_error_init was already // called, and error's will be returned to the caller without logging. The -// return value is NULL iff an error was set. The client must free the error if -// set. +// return value is nullptr iff an error was set. The client must free the +// error if set. DBusMessage* dbus_func_args_timeout_valist(DBusConnection* conn, int timeout_ms, DBusError* err, @@ -591,7 +591,7 @@ DBusMessage * dbus_func_args(DBusConnection *conn, DBusMessage *ret; va_list lst; va_start(lst, first_arg_type); - ret = dbus_func_args_timeout_valist(conn, -1, NULL, + ret = dbus_func_args_timeout_valist(conn, -1, nullptr, path, ifc, func, first_arg_type, lst); va_end(lst); diff --git a/ipc/dbus/DBusUtils.h b/ipc/dbus/DBusUtils.h index 839e9b5985f..7086fae56aa 100644 --- a/ipc/dbus/DBusUtils.h +++ b/ipc/dbus/DBusUtils.h @@ -93,7 +93,7 @@ typedef void (*DBusCallback)(DBusMessage *, void *); void log_and_free_dbus_error(DBusError* err, const char* function, - DBusMessage* msg = NULL); + DBusMessage* msg = nullptr); dbus_bool_t dbus_func_send(DBusConnection *aConnection, dbus_uint32_t *aSerial, diff --git a/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp index 8c4958c3a83..c440fe82a53 100644 --- a/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp +++ b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp @@ -41,7 +41,7 @@ bool gChildDone; //----------------------------------------------------------------------------- // data/functions accessed by both parent and child processes -char* gIPDLUnitTestName = NULL; +char* gIPDLUnitTestName = nullptr; const char* const IPDLUnitTestName() @@ -103,7 +103,7 @@ ${ENUM_TO_STRINGS} //----------------------------------------------------------------------------- default: - return NULL; + return nullptr; } } diff --git a/ipc/ipdl/test/cxx/TestCrashCleanup.cpp b/ipc/ipdl/test/cxx/TestCrashCleanup.cpp index 69f353f28d7..308e57395fb 100644 --- a/ipc/ipdl/test/cxx/TestCrashCleanup.cpp +++ b/ipc/ipdl/test/cxx/TestCrashCleanup.cpp @@ -26,7 +26,7 @@ void DeleteSubprocess(Mutex* mutex, CondVar* cvar) MutexAutoLock lock(*mutex); delete gSubprocess; - gSubprocess = NULL; + gSubprocess = nullptr; cvar->Notify(); } @@ -34,7 +34,7 @@ void DeleteSubprocess(Mutex* mutex, CondVar* cvar) void DeleteTheWorld() { delete static_cast(gParentActor); - gParentActor = NULL; + gParentActor = nullptr; // needs to be synchronous to avoid affecting event ordering on // the main thread diff --git a/ipc/ipdl/test/cxx/TestDataStructures.cpp b/ipc/ipdl/test/cxx/TestDataStructures.cpp index 181eecf270a..db48e6e291b 100644 --- a/ipc/ipdl/test/cxx/TestDataStructures.cpp +++ b/ipc/ipdl/test/cxx/TestDataStructures.cpp @@ -951,7 +951,7 @@ TestDataStructuresChild::Test17() attrs.specific() = BarAttrs(1.0f); InfallibleTArray ops; - ops.AppendElement(SetAttrs(NULL, mKids[0], attrs)); + ops.AppendElement(SetAttrs(nullptr, mKids[0], attrs)); if (!SendTest17(ops)) fail("sending Test17"); diff --git a/ipc/ipdl/test/cxx/TestFailedCtor.h b/ipc/ipdl/test/cxx/TestFailedCtor.h index 9003902c86f..c189aec8177 100644 --- a/ipc/ipdl/test/cxx/TestFailedCtor.h +++ b/ipc/ipdl/test/cxx/TestFailedCtor.h @@ -80,7 +80,7 @@ class TestFailedCtorSubParent : public PTestFailedCtorSubParent { public: - TestFailedCtorSubParent() : mOne(NULL), mTwo(NULL), mThree(NULL) { } + TestFailedCtorSubParent() : mOne(nullptr), mTwo(nullptr), mThree(nullptr) { } virtual ~TestFailedCtorSubParent(); protected: diff --git a/ipc/ipdl/test/cxx/TestRPCErrorCleanup.cpp b/ipc/ipdl/test/cxx/TestRPCErrorCleanup.cpp index 9980504ee4e..a2cc8ddf617 100644 --- a/ipc/ipdl/test/cxx/TestRPCErrorCleanup.cpp +++ b/ipc/ipdl/test/cxx/TestRPCErrorCleanup.cpp @@ -26,7 +26,7 @@ void DeleteSubprocess(Mutex* mutex, CondVar* cvar) MutexAutoLock lock(*mutex); delete gSubprocess; - gSubprocess = NULL; + gSubprocess = nullptr; cvar->Notify(); } @@ -34,7 +34,7 @@ void DeleteSubprocess(Mutex* mutex, CondVar* cvar) void DeleteTheWorld() { delete static_cast(gParentActor); - gParentActor = NULL; + gParentActor = nullptr; // needs to be synchronous to avoid affecting event ordering on // the main thread diff --git a/ipc/ipdl/test/cxx/TestRPCShutdownRace.cpp b/ipc/ipdl/test/cxx/TestRPCShutdownRace.cpp index dc366bef687..a913bcec0e2 100644 --- a/ipc/ipdl/test/cxx/TestRPCShutdownRace.cpp +++ b/ipc/ipdl/test/cxx/TestRPCShutdownRace.cpp @@ -25,7 +25,7 @@ namespace { void DeleteSubprocess() { delete gSubprocess; - gSubprocess = NULL; + gSubprocess = nullptr; } void Done() @@ -80,7 +80,7 @@ TestRPCShutdownRaceParent::StartShuttingDown() Close(); delete static_cast(gParentActor); - gParentActor = NULL; + gParentActor = nullptr; XRE_GetIOMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(DeleteSubprocess)); diff --git a/ipc/testshell/TestShellParent.h b/ipc/testshell/TestShellParent.h index c975dace56d..77d66284ba2 100644 --- a/ipc/testshell/TestShellParent.h +++ b/ipc/testshell/TestShellParent.h @@ -40,7 +40,7 @@ public: class TestShellCommandParent : public PTestShellCommandParent { public: - TestShellCommandParent() : mCx(NULL) { } + TestShellCommandParent() : mCx(nullptr) { } bool SetCallback(JSContext* aCx, JS::Value aCallback); diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 15c45293807..a62577bfb23 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -281,11 +281,11 @@ DumpHeap(JSContext *cx, JS::Value *vp) { JSAutoByteString fileName; - void* startThing = NULL; + void* startThing = nullptr; JSGCTraceKind startTraceKind = JSTRACE_OBJECT; - void *thingToFind = NULL; + void *thingToFind = nullptr; size_t maxDepth = (size_t)-1; - void *thingToIgnore = NULL; + void *thingToIgnore = nullptr; FILE *dumpFile; bool ok; @@ -486,7 +486,7 @@ XPCShellEnvironment::ProcessFile(JSContext *cx, ok = JS_ExecuteScript(cx, obj, script, result.address()); if (ok && result != JSVAL_VOID) { /* Suppress error reports from JS_ValueToString(). */ - older = JS_SetErrorReporter(cx, NULL); + older = JS_SetErrorReporter(cx, nullptr); str = JS_ValueToString(cx, result); JSAutoByteString bytes; if (str) @@ -702,7 +702,7 @@ XPCShellEnvironment::EvaluateString(const nsString& aString, JS::Rooted result(cx); bool ok = JS_ExecuteScript(cx, global, script, result.address()); if (ok && result != JSVAL_VOID) { - JSErrorReporter old = JS_SetErrorReporter(cx, NULL); + JSErrorReporter old = JS_SetErrorReporter(cx, nullptr); JSString* str = JS_ValueToString(cx, result); nsDependentJSString depStr; if (str) From ac65651663d5bc30b0fafba16b8eaf2b862e7c99 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Fri, 23 Aug 2013 15:51:58 -0400 Subject: [PATCH 05/87] Bug 784739 - Switch from NULL to nullptr in ipc/glue/. r=ehsan --- ipc/glue/AsyncChannel.cpp | 10 ++--- ipc/glue/BrowserProcessSubThread.cpp | 22 +++++------ ipc/glue/CrossProcessMutex_windows.cpp | 4 +- ipc/glue/IPCMessageUtils.h | 6 +-- ipc/glue/ProcessChild.cpp | 2 +- ipc/glue/Shmem.h | 8 ++-- ipc/glue/SyncChannel.cpp | 4 +- ipc/glue/WindowsMessageLoop.cpp | 54 +++++++++++++------------- 8 files changed, 55 insertions(+), 55 deletions(-) diff --git a/ipc/glue/AsyncChannel.cpp b/ipc/glue/AsyncChannel.cpp index 593963bda7b..7c524f3a253 100644 --- a/ipc/glue/AsyncChannel.cpp +++ b/ipc/glue/AsyncChannel.cpp @@ -90,7 +90,7 @@ AsyncChannel::Link::~Link() AsyncChannel::ProcessLink::ProcessLink(AsyncChannel *aChan) : Link(aChan) - , mExistingListener(NULL) + , mExistingListener(nullptr) { } @@ -289,8 +289,8 @@ AsyncChannel::AsyncChannel(AsyncListener* aListener) mChannelState(ChannelClosed), mWorkerLoop(), mChild(false), - mChannelErrorTask(NULL), - mLink(NULL), + mChannelErrorTask(nullptr), + mLink(nullptr), mWorkerLoopID(-1) { MOZ_COUNT_CTOR(AsyncChannel); @@ -525,7 +525,7 @@ AsyncChannel::OnNotifyMaybeChannelError() AssertWorkerThread(); mMonitor->AssertNotCurrentThreadOwns(); - mChannelErrorTask = NULL; + mChannelErrorTask = nullptr; // OnChannelError holds mMonitor when it posts this task and this // task cannot be allowed to run until OnChannelError has @@ -604,7 +604,7 @@ AsyncChannel::Clear() if (mChannelErrorTask) { mChannelErrorTask->Cancel(); - mChannelErrorTask = NULL; + mChannelErrorTask = nullptr; } } diff --git a/ipc/glue/BrowserProcessSubThread.cpp b/ipc/glue/BrowserProcessSubThread.cpp index edcf40168e0..f0a6ae39575 100644 --- a/ipc/glue/BrowserProcessSubThread.cpp +++ b/ipc/glue/BrowserProcessSubThread.cpp @@ -32,23 +32,23 @@ static const char* kBrowserThreadNames[BrowserProcessSubThread::ID_COUNT] = { Lock BrowserProcessSubThread::sLock; BrowserProcessSubThread* BrowserProcessSubThread::sBrowserThreads[ID_COUNT] = { - NULL, // IO -// NULL, // FILE -// NULL, // DB -// NULL, // HISTORY + nullptr, // IO +// nullptr, // FILE +// nullptr, // DB +// nullptr, // HISTORY #if defined(OS_LINUX) - NULL, // BACKGROUND_X11 + nullptr, // BACKGROUND_X11 #endif }; BrowserProcessSubThread::BrowserProcessSubThread(ID aId) : base::Thread(kBrowserThreadNames[aId]), mIdentifier(aId), - mNotificationService(NULL) + mNotificationService(nullptr) { AutoLock lock(sLock); DCHECK(aId >= 0 && aId < ID_COUNT); - DCHECK(sBrowserThreads[aId] == NULL); + DCHECK(sBrowserThreads[aId] == nullptr); sBrowserThreads[aId] = this; } @@ -56,7 +56,7 @@ BrowserProcessSubThread::~BrowserProcessSubThread() { Stop(); {AutoLock lock(sLock); - sBrowserThreads[mIdentifier] = NULL; + sBrowserThreads[mIdentifier] = nullptr; } } @@ -66,7 +66,7 @@ BrowserProcessSubThread::Init() { #if defined(OS_WIN) // Initializes the COM library on the current thread. - CoInitialize(NULL); + CoInitialize(nullptr); #endif mNotificationService = new NotificationService(); } @@ -75,7 +75,7 @@ void BrowserProcessSubThread::CleanUp() { delete mNotificationService; - mNotificationService = NULL; + mNotificationService = nullptr; #if defined(OS_WIN) // Closes the COM library on the current thread. CoInitialize must @@ -94,7 +94,7 @@ BrowserProcessSubThread::GetMessageLoop(ID aId) if (sBrowserThreads[aId]) return sBrowserThreads[aId]->message_loop(); - return NULL; + return nullptr; } } // namespace ipc diff --git a/ipc/glue/CrossProcessMutex_windows.cpp b/ipc/glue/CrossProcessMutex_windows.cpp index 0b75e740125..df8f620186e 100644 --- a/ipc/glue/CrossProcessMutex_windows.cpp +++ b/ipc/glue/CrossProcessMutex_windows.cpp @@ -19,7 +19,7 @@ CrossProcessMutex::CrossProcessMutex(const char*) // We explicitly share this using DuplicateHandle, we do -not- want this to // be inherited by child processes by default! So no security attributes are // given. - mMutex = ::CreateMutexA(NULL, FALSE, NULL); + mMutex = ::CreateMutexA(nullptr, FALSE, nullptr); if (!mMutex) { NS_RUNTIMEABORT("This shouldn't happen - failed to create mutex!"); } @@ -66,7 +66,7 @@ CrossProcessMutex::ShareToProcess(ProcessHandle aHandle) 0, FALSE, DUPLICATE_SAME_ACCESS); if (!succeeded) { - return NULL; + return nullptr; } return newHandle; diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index 83e267b25ed..eb6d1642476 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -210,7 +210,7 @@ struct ParamTraits aMsg->WriteBool(isVoid); if (isVoid) - // represents a NULL pointer + // represents a nullptr pointer return; uint32_t length = aParam.Length(); @@ -260,7 +260,7 @@ struct ParamTraits aMsg->WriteBool(isVoid); if (isVoid) - // represents a NULL pointer + // represents a nullptr pointer return; uint32_t length = aParam.Length(); @@ -581,7 +581,7 @@ struct ParamTraits return false; } } else { - aResult->data = NULL; + aResult->data = nullptr; } return true; diff --git a/ipc/glue/ProcessChild.cpp b/ipc/glue/ProcessChild.cpp index 073091412f0..2b12526d764 100644 --- a/ipc/glue/ProcessChild.cpp +++ b/ipc/glue/ProcessChild.cpp @@ -27,7 +27,7 @@ ProcessChild::ProcessChild(ProcessHandle parentHandle) ProcessChild::~ProcessChild() { - gProcessChild = NULL; + gProcessChild = nullptr; } } // namespace ipc diff --git a/ipc/glue/Shmem.h b/ipc/glue/Shmem.h index 4fe330f3bfa..6b970005044 100644 --- a/ipc/glue/Shmem.h +++ b/ipc/glue/Shmem.h @@ -130,7 +130,7 @@ public: bool IsWritable() const { - return mSegment != NULL; + return mSegment != nullptr; } // Returns whether this Shmem is readable by you, and thus whether you can @@ -138,7 +138,7 @@ public: bool IsReadable() const { - return mSegment != NULL; + return mSegment != nullptr; } // Return a pointer to the user-visible data segment. @@ -203,7 +203,7 @@ public: // Prepare this to be shared with |aProcess|. Return an IPC message // that contains enough information for the other process to map // this segment in OpenExisting() below. Return a new message if - // successful (owned by the caller), NULL if not. + // successful (owned by the caller), nullptr if not. IPC::Message* ShareTo(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, base::ProcessHandle aProcess, @@ -212,7 +212,7 @@ public: // Stop sharing this with |aProcess|. Return an IPC message that // contains enough information for the other process to unmap this // segment. Return a new message if successful (owned by the - // caller), NULL if not. + // caller), nullptr if not. IPC::Message* UnshareFrom(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, base::ProcessHandle aProcess, diff --git a/ipc/glue/SyncChannel.cpp b/ipc/glue/SyncChannel.cpp index 7d9afb40f5f..0bd91e90b44 100644 --- a/ipc/glue/SyncChannel.cpp +++ b/ipc/glue/SyncChannel.cpp @@ -30,7 +30,7 @@ const int32_t SyncChannel::kNoTimeout = INT32_MIN; SyncChannel::SyncChannel(SyncListener* aListener) : AsyncChannel(aListener) #ifdef OS_WIN - , mTopFrame(NULL) + , mTopFrame(nullptr) #endif , mPendingReply(0) , mProcessingSyncMessage(false) @@ -40,7 +40,7 @@ SyncChannel::SyncChannel(SyncListener* aListener) { MOZ_COUNT_CTOR(SyncChannel); #ifdef OS_WIN - mEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + mEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); NS_ASSERTION(mEvent, "CreateEvent failed! Nothing is going to work!"); #endif } diff --git a/ipc/glue/WindowsMessageLoop.cpp b/ipc/glue/WindowsMessageLoop.cpp index 7d8c9eb936e..84a1174901f 100644 --- a/ipc/glue/WindowsMessageLoop.cpp +++ b/ipc/glue/WindowsMessageLoop.cpp @@ -98,8 +98,8 @@ nsTArray* gNeuteredWindows = nullptr; typedef nsTArray > DeferredMessageArray; DeferredMessageArray* gDeferredMessages = nullptr; -HHOOK gDeferredGetMsgHook = NULL; -HHOOK gDeferredCallWndProcHook = NULL; +HHOOK gDeferredGetMsgHook = nullptr; +HHOOK gDeferredCallWndProcHook = nullptr; DWORD gUIThreadId = 0; @@ -141,7 +141,7 @@ DeferredMessageHook(int nCode, } // Always call the next hook. - return CallNextHookEx(NULL, nCode, wParam, lParam); + return CallNextHookEx(nullptr, nCode, wParam, lParam); } void @@ -152,9 +152,9 @@ ScheduleDeferredMessageRun() NS_ASSERTION(gDeferredMessages->Length(), "No deferred messages?!"); gDeferredGetMsgHook = ::SetWindowsHookEx(WH_GETMESSAGE, DeferredMessageHook, - NULL, gUIThreadId); + nullptr, gUIThreadId); gDeferredCallWndProcHook = ::SetWindowsHookEx(WH_CALLWNDPROC, - DeferredMessageHook, NULL, + DeferredMessageHook, nullptr, gUIThreadId); NS_ASSERTION(gDeferredGetMsgHook && gDeferredCallWndProcHook, "Failed to set hooks!"); @@ -444,9 +444,9 @@ NeuterWindowProcedure(HWND hWnd) NS_ASSERTION(!GetProp(hWnd, kOldWndProcProp), "This should always be null!"); - // It's possible to get NULL out of SetWindowLongPtr, and the only way to know - // if that's a valid old value is to use GetLastError. Clear the error here so - // we can tell. + // It's possible to get nullptr out of SetWindowLongPtr, and the only way to + // know if that's a valid old value is to use GetLastError. Clear the error + // here so we can tell. SetLastError(ERROR_SUCCESS); LONG_PTR currentWndProc = @@ -508,7 +508,7 @@ CallWindowProcedureHook(int nCode, } } } - return CallNextHookEx(NULL, nCode, wParam, lParam); + return CallNextHookEx(nullptr, nCode, wParam, lParam); } inline void @@ -618,7 +618,7 @@ RPCChannel::SyncStackFrame::~SyncStackFrame() if (!mStaticPrev) { NS_ASSERTION(gNeuteredWindows, "Bad pointer!"); delete gNeuteredWindows; - gNeuteredWindows = NULL; + gNeuteredWindows = nullptr; } } @@ -687,7 +687,7 @@ RPCChannel::SpinInternalEventLoop() } // Retrieve window or thread messages - if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { + if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { // The child UI should have been destroyed before the app is closed, in // which case, we should never get this here. if (msg.message == WM_QUIT) { @@ -737,7 +737,7 @@ SyncChannel::WaitForNotify() // We only do this to ensure that we won't get stuck in // MsgWaitForMultipleObjects below. - timerId = SetTimer(NULL, 0, mTimeoutMs, NULL); + timerId = SetTimer(nullptr, 0, mTimeoutMs, nullptr); NS_ASSERTION(timerId, "SetTimer failed!"); } @@ -747,7 +747,7 @@ SyncChannel::WaitForNotify() SyncChannel::SetIsPumpingMessages(true); HHOOK windowHook = SetWindowsHookEx(WH_CALLWNDPROC, CallWindowProcedureHook, - NULL, gUIThreadId); + nullptr, gUIThreadId); NS_ASSERTION(windowHook, "Failed to set hook!"); { @@ -806,7 +806,7 @@ SyncChannel::WaitForNotify() // have woken up for a message designated for a window in another thread. // If we loop immediately then we could enter a tight loop, so we'll give // up our time slice here to let the child process its message. - if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE) && + if (!PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE) && !haveSentMessagesPending) { // Message was for child, we should wait a bit. SwitchToThread(); @@ -828,7 +828,7 @@ SyncChannel::WaitForNotify() ScheduleDeferredMessageRun(); if (timerId) { - KillTimer(NULL, timerId); + KillTimer(nullptr, timerId); } SyncChannel::SetIsPumpingMessages(false); @@ -862,8 +862,8 @@ RPCChannel::WaitForNotify() // windowHook is used as a flag variable for the loop below: if it is set // and we start to spin a nested event loop, we need to clear the hook and // process deferred/pending messages. - // If windowHook is NULL, SyncChannel::IsPumpingMessages should be false. - HHOOK windowHook = NULL; + // If windowHook is nullptr, SyncChannel::IsPumpingMessages should be false. + HHOOK windowHook = nullptr; while (1) { NS_ASSERTION((!!windowHook) == SyncChannel::IsPumpingMessages(), @@ -872,10 +872,10 @@ RPCChannel::WaitForNotify() if (mTopFrame->mSpinNestedEvents) { if (windowHook) { UnhookWindowsHookEx(windowHook); - windowHook = NULL; + windowHook = nullptr; if (timerId) { - KillTimer(NULL, timerId); + KillTimer(nullptr, timerId); timerId = 0; } @@ -899,14 +899,14 @@ RPCChannel::WaitForNotify() if (!windowHook) { SyncChannel::SetIsPumpingMessages(true); windowHook = SetWindowsHookEx(WH_CALLWNDPROC, CallWindowProcedureHook, - NULL, gUIThreadId); + nullptr, gUIThreadId); NS_ASSERTION(windowHook, "Failed to set hook!"); NS_ASSERTION(!timerId, "Timer already initialized?"); if (mTimeoutMs != kNoTimeout) { InitTimeoutData(&timeoutData, mTimeoutMs); - timerId = SetTimer(NULL, 0, mTimeoutMs, NULL); + timerId = SetTimer(nullptr, 0, mTimeoutMs, nullptr); NS_ASSERTION(timerId, "SetTimer failed!"); } } @@ -945,7 +945,7 @@ RPCChannel::WaitForNotify() // PeekMessage markes the messages as "old" so that they don't wake up // MsgWaitForMultipleObjects every time. - if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE) && + if (!PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE) && !haveSentMessagesPending) { // Message was for child, we should wait a bit. SwitchToThread(); @@ -967,7 +967,7 @@ RPCChannel::WaitForNotify() ScheduleDeferredMessageRun(); if (timerId) { - KillTimer(NULL, timerId); + KillTimer(nullptr, timerId); } } @@ -1017,7 +1017,7 @@ DeferredRedrawMessage::Run() #ifdef DEBUG BOOL ret = #endif - RedrawWindow(hWnd, NULL, NULL, flags); + RedrawWindow(hWnd, nullptr, nullptr, flags); NS_ASSERTION(ret, "RedrawWindow failed!"); } @@ -1060,7 +1060,7 @@ DeferredSettingChangeMessage::DeferredSettingChangeMessage(HWND aHWnd, lParam = reinterpret_cast(lParamString); } else { - lParamString = NULL; + lParamString = nullptr; lParam = 0; } } @@ -1085,7 +1085,7 @@ DeferredWindowPosMessage::DeferredWindowPosMessage(HWND aHWnd, else { RECT* arg = reinterpret_cast(aLParam); windowPos.hwnd = aHWnd; - windowPos.hwndInsertAfter = NULL; + windowPos.hwndInsertAfter = nullptr; windowPos.x = arg->left; windowPos.y = arg->top; windowPos.cx = arg->right - arg->left; @@ -1163,7 +1163,7 @@ DeferredCopyDataMessage::DeferredCopyDataMessage(HWND aHWnd, } } else { - copyData.lpData = NULL; + copyData.lpData = nullptr; } lParam = reinterpret_cast(©Data); From 214420a48ab91b9b356b9e1092aa88ac31a18b46 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Fri, 23 Aug 2013 13:56:20 -0400 Subject: [PATCH 06/87] Bug 908180 - Don't #include nsGUIEvent.h in nsIPresShell.h. r=mounir --- content/base/src/nsGenConImageContent.cpp | 1 + content/html/content/src/HTMLFieldSetElement.cpp | 1 + content/html/content/src/HTMLLabelElement.cpp | 2 ++ content/html/content/src/HTMLMenuElement.cpp | 1 + content/html/content/src/HTMLMenuItemElement.cpp | 1 + image/src/VectorImage.cpp | 1 + layout/base/nsIPresShell.h | 3 ++- layout/base/nsLayoutUtils.h | 1 + layout/base/nsPresContext.h | 1 + layout/generic/Selection.h | 1 + layout/inspector/src/inFlasher.cpp | 1 + 11 files changed, 13 insertions(+), 1 deletion(-) diff --git a/content/base/src/nsGenConImageContent.cpp b/content/base/src/nsGenConImageContent.cpp index 11939443804..8d6645136b2 100644 --- a/content/base/src/nsGenConImageContent.cpp +++ b/content/base/src/nsGenConImageContent.cpp @@ -16,6 +16,7 @@ #include "imgIRequest.h" #include "nsEventStates.h" #include "nsEventDispatcher.h" +#include "nsGUIEvent.h" class nsGenConImageContent MOZ_FINAL : public nsXMLElement, public nsImageLoadingContent diff --git a/content/html/content/src/HTMLFieldSetElement.cpp b/content/html/content/src/HTMLFieldSetElement.cpp index 0e8c2df469f..a8951f93202 100644 --- a/content/html/content/src/HTMLFieldSetElement.cpp +++ b/content/html/content/src/HTMLFieldSetElement.cpp @@ -7,6 +7,7 @@ #include "mozilla/dom/HTMLFieldSetElementBinding.h" #include "nsContentList.h" #include "nsEventDispatcher.h" +#include "nsGUIEvent.h" NS_IMPL_NS_NEW_HTML_ELEMENT(FieldSet) diff --git a/content/html/content/src/HTMLLabelElement.cpp b/content/html/content/src/HTMLLabelElement.cpp index be2ea171820..eb6c72f1887 100644 --- a/content/html/content/src/HTMLLabelElement.cpp +++ b/content/html/content/src/HTMLLabelElement.cpp @@ -10,6 +10,8 @@ #include "mozilla/dom/HTMLLabelElementBinding.h" #include "nsEventDispatcher.h" #include "nsFocusManager.h" +#include "nsGUIEvent.h" +#include "nsIDOMMouseEvent.h" // construction, destruction diff --git a/content/html/content/src/HTMLMenuElement.cpp b/content/html/content/src/HTMLMenuElement.cpp index 625b2022458..d302cbec54e 100644 --- a/content/html/content/src/HTMLMenuElement.cpp +++ b/content/html/content/src/HTMLMenuElement.cpp @@ -10,6 +10,7 @@ #include "nsAttrValueInlines.h" #include "nsContentUtils.h" #include "nsEventDispatcher.h" +#include "nsGUIEvent.h" #include "nsXULContextMenuBuilder.h" NS_IMPL_NS_NEW_HTML_ELEMENT(Menu) diff --git a/content/html/content/src/HTMLMenuItemElement.cpp b/content/html/content/src/HTMLMenuItemElement.cpp index a941c0b2cef..73543f76b1a 100644 --- a/content/html/content/src/HTMLMenuItemElement.cpp +++ b/content/html/content/src/HTMLMenuItemElement.cpp @@ -9,6 +9,7 @@ #include "nsAttrValueInlines.h" #include "nsContentUtils.h" #include "nsEventDispatcher.h" +#include "nsGUIEvent.h" NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem) diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index b7adeec3180..489804492d5 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -16,6 +16,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/dom/SVGSVGElement.h" #include "nsComponentManagerUtils.h" +#include "nsIDOMEvent.h" #include "nsIObserverService.h" #include "nsIPresShell.h" #include "nsIStreamListener.h" diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 7ad1454d0e6..2f779bdb1b8 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -21,6 +21,7 @@ #define nsIPresShell_h___ #include "mozilla/MemoryReporting.h" +#include "gfxPoint.h" #include "nsTHashtable.h" #include "nsHashKeys.h" #include "nsISupports.h" @@ -35,7 +36,6 @@ #include "nsWeakReference.h" #include // for FILE definition #include "nsChangeHint.h" -#include "nsGUIEvent.h" #include "nsRefPtrHashtable.h" #include "nsEventStates.h" #include "nsPresArena.h" @@ -95,6 +95,7 @@ class Selection; namespace dom { class Element; +class Touch; } // namespace dom namespace layers{ diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index d1f8803e381..dc7bda1be73 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -37,6 +37,7 @@ class imgIContainer; #include "nsHTMLReflowState.h" #include "FrameMetrics.h" #include "gfx3DMatrix.h" +#include "nsIWidget.h" #include #include diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 31f4765a5a8..2dc111fe966 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -16,6 +16,7 @@ #include "nsRect.h" #include "nsDeviceContext.h" #include "nsFont.h" +#include "nsIAtom.h" #include "nsIObserver.h" #include "nsITimer.h" #include "nsCRT.h" diff --git a/layout/generic/Selection.h b/layout/generic/Selection.h index 65582a49a5f..f19e7b3ff77 100644 --- a/layout/generic/Selection.h +++ b/layout/generic/Selection.h @@ -9,6 +9,7 @@ #include "nsIWeakReference.h" +#include "nsGUIEvent.h" #include "nsISelection.h" #include "nsISelectionController.h" #include "nsISelectionPrivate.h" diff --git a/layout/inspector/src/inFlasher.cpp b/layout/inspector/src/inFlasher.cpp index ad2e8b813c3..800b8a0d19a 100644 --- a/layout/inspector/src/inFlasher.cpp +++ b/layout/inspector/src/inFlasher.cpp @@ -9,6 +9,7 @@ #include "nsIServiceManager.h" #include "nsIPresShell.h" #include "nsIFrame.h" +#include "nsIWidget.h" #include "nsReadableUtils.h" #include "nsRenderingContext.h" From 2faab8bc9eb4d2d64171a06d7f16b69100f1494e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 16:20:07 -0400 Subject: [PATCH 07/87] Bug 908724 - Avoid #including nsPresContext.h in nsIScrollableFrame.h; r=mats nsPresContext.h pulls in a large number of headers which should not be needed in nsIScrollableFrame, if we just move ScrollbarStyles to its own header --- content/events/src/nsEventStateManager.cpp | 5 ++-- layout/base/ScrollbarStyles.h | 31 ++++++++++++++++++++++ layout/base/moz.build | 1 + layout/base/nsLayoutUtils.cpp | 4 +-- layout/base/nsPresContext.h | 18 +++---------- layout/base/nsPresShell.cpp | 2 +- layout/forms/nsListControlFrame.cpp | 5 ++-- layout/forms/nsListControlFrame.h | 2 +- layout/generic/nsFrame.cpp | 2 +- layout/generic/nsGfxScrollFrame.cpp | 12 ++++----- layout/generic/nsGfxScrollFrame.h | 7 +++-- layout/generic/nsIScrollableFrame.h | 8 +++--- layout/style/AnimationCommon.cpp | 2 +- layout/style/nsRuleNode.cpp | 2 +- 14 files changed, 59 insertions(+), 42 deletions(-) create mode 100644 layout/base/ScrollbarStyles.h diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index c6954ffb13f..e21487c376f 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -2596,7 +2596,7 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame, return frameToScroll; } - nsPresContext::ScrollbarStyles ss = frameToScroll->GetScrollbarStyles(); + ScrollbarStyles ss = frameToScroll->GetScrollbarStyles(); bool hiddenForV = (NS_STYLE_OVERFLOW_HIDDEN == ss.mVertical); bool hiddenForH = (NS_STYLE_OVERFLOW_HIDDEN == ss.mHorizontal); if ((hiddenForV && hiddenForH) || @@ -2705,8 +2705,7 @@ nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame, ComputeScrollAmountForDefaultAction(aEvent, scrollAmountInDevPixels); // Don't scroll around the axis whose overflow style is hidden. - nsPresContext::ScrollbarStyles overflowStyle = - aScrollableFrame->GetScrollbarStyles(); + ScrollbarStyles overflowStyle = aScrollableFrame->GetScrollbarStyles(); if (overflowStyle.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) { actualDevPixelScrollAmount.x = 0; } diff --git a/layout/base/ScrollbarStyles.h b/layout/base/ScrollbarStyles.h new file mode 100644 index 00000000000..0db0e0949c0 --- /dev/null +++ b/layout/base/ScrollbarStyles.h @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ScrollbarStyles_h +#define ScrollbarStyles_h + +#include + +namespace mozilla { + +struct ScrollbarStyles +{ + // Always one of NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN, + // or NS_STYLE_OVERFLOW_AUTO. + uint8_t mHorizontal; + uint8_t mVertical; + ScrollbarStyles(uint8_t h, uint8_t v) : mHorizontal(h), mVertical(v) {} + ScrollbarStyles() {} + bool operator==(const ScrollbarStyles& aStyles) const { + return aStyles.mHorizontal == mHorizontal && aStyles.mVertical == mVertical; + } + bool operator!=(const ScrollbarStyles& aStyles) const { + return aStyles.mHorizontal != mHorizontal || aStyles.mVertical != mVertical; + } +}; + +} + +#endif diff --git a/layout/base/moz.build b/layout/base/moz.build index fb9e198fe95..411d2acef2e 100644 --- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -30,6 +30,7 @@ EXPORTS += [ 'DisplayListClipState.h', 'FrameLayerBuilder.h', 'FramePropertyTable.h', + 'ScrollbarStyles.h', 'StackArena.h', 'Units.h', 'nsArenaMemoryStats.h', diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index cfa068931e4..a0395f27425 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1144,7 +1144,7 @@ nsLayoutUtils::GetNearestScrollableFrameForDirection(nsIFrame* aFrame, for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) { nsIScrollableFrame* scrollableFrame = do_QueryFrame(f); if (scrollableFrame) { - nsPresContext::ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles(); + ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles(); uint32_t directions = scrollableFrame->GetPerceivedScrollingDirections(); if (aDirection == eVertical ? (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN && @@ -1166,7 +1166,7 @@ nsLayoutUtils::GetNearestScrollableFrame(nsIFrame* aFrame, uint32_t aFlags) f->GetParent() : nsLayoutUtils::GetCrossDocParentFrame(f)) { nsIScrollableFrame* scrollableFrame = do_QueryFrame(f); if (scrollableFrame) { - nsPresContext::ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles(); + ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles(); if ((aFlags & SCROLLABLE_INCLUDE_HIDDEN) || ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN || ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 2dc111fe966..3c3b6d8a679 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -33,6 +33,7 @@ #include "mozilla/TimeStamp.h" #include "prclist.h" #include "nsThreadUtils.h" +#include "ScrollbarStyles.h" #ifdef IBMBIDI class nsBidiPresUtils; @@ -628,25 +629,12 @@ public: nscoord RoundAppUnitsToNearestDevPixels(nscoord aAppUnits) const { return DevPixelsToAppUnits(AppUnitsToDevPixels(aAppUnits)); } - struct ScrollbarStyles { - // Always one of NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN, - // or NS_STYLE_OVERFLOW_AUTO. - uint8_t mHorizontal, mVertical; - ScrollbarStyles(uint8_t h, uint8_t v) : mHorizontal(h), mVertical(v) {} - ScrollbarStyles() {} - bool operator==(const ScrollbarStyles& aStyles) const { - return aStyles.mHorizontal == mHorizontal && aStyles.mVertical == mVertical; - } - bool operator!=(const ScrollbarStyles& aStyles) const { - return aStyles.mHorizontal != mHorizontal || aStyles.mVertical != mVertical; - } - }; void SetViewportOverflowOverride(uint8_t aX, uint8_t aY) { mViewportStyleOverflow.mHorizontal = aX; mViewportStyleOverflow.mVertical = aY; } - ScrollbarStyles GetViewportOverflowOverride() + mozilla::ScrollbarStyles GetViewportOverflowOverride() { return mViewportStyleOverflow; } @@ -1223,7 +1211,7 @@ protected: nscolor mBodyTextColor; - ScrollbarStyles mViewportStyleOverflow; + mozilla::ScrollbarStyles mViewportStyleOverflow; uint8_t mFocusRingWidth; bool mExistThrottledUpdates; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index fa9ad5298ed..0e3dd0b473c 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -3107,7 +3107,7 @@ static void ScrollToShowRect(nsIFrame* aFrame, aHorizontal.mWhenToScroll == nsIPresShell::SCROLL_IF_NOT_VISIBLE) { lineSize = aFrameAsScrollable->GetLineScrollAmount(); } - nsPresContext::ScrollbarStyles ss = aFrameAsScrollable->GetScrollbarStyles(); + ScrollbarStyles ss = aFrameAsScrollable->GetScrollbarStyles(); nsRect allowedRange(scrollPt, nsSize(0, 0)); bool needToScroll = false; uint32_t directions = aFrameAsScrollable->GetPerceivedScrollingDirections(); diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 89ea541097c..2b8d6e7b137 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -594,15 +594,14 @@ nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext, return nsHTMLScrollFrame::Reflow(aPresContext, aDesiredSize, state, aStatus); } -nsGfxScrollFrameInner::ScrollbarStyles +ScrollbarStyles nsListControlFrame::GetScrollbarStyles() const { // We can't express this in the style system yet; when we can, this can go away // and GetScrollbarStyles can be devirtualized int32_t verticalStyle = IsInDropDownMode() ? NS_STYLE_OVERFLOW_AUTO : NS_STYLE_OVERFLOW_SCROLL; - return nsGfxScrollFrameInner::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, - verticalStyle); + return ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, verticalStyle); } bool diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index b6ee18feb30..ee2ad60874d 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -107,7 +107,7 @@ public: virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE; virtual void SetFocus(bool aOn = true, bool aRepaint = false) MOZ_OVERRIDE; - virtual nsGfxScrollFrameInner::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE; + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE; virtual bool ShouldPropagateComputedHeightToScrolledContent() const MOZ_OVERRIDE; // for accessibility purposes diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 2feecd5b75c..e92b398d434 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -7332,7 +7332,7 @@ nsIFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse) // will be enough to make them keyboard scrollable. nsIScrollableFrame *scrollFrame = do_QueryFrame(this); if (scrollFrame && - scrollFrame->GetScrollbarStyles() != nsIScrollableFrame::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) && + scrollFrame->GetScrollbarStyles() != ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) && !scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) { // Scroll bars will be used for overflow isFocusable = true; diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index acf5dd0ad25..dcdae94ed8b 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -159,7 +159,7 @@ nsHTMLScrollFrame::GetType() const struct MOZ_STACK_CLASS ScrollReflowState { const nsHTMLReflowState& mReflowState; nsBoxLayoutState mBoxState; - nsGfxScrollFrameInner::ScrollbarStyles mStyles; + ScrollbarStyles mStyles; nsMargin mComputedBorder; // === Filled in by ReflowScrolledFrame === @@ -652,7 +652,7 @@ nsHTMLScrollFrame::PlaceScrollArea(const ScrollReflowState& aState, nscoord nsHTMLScrollFrame::GetIntrinsicVScrollbarWidth(nsRenderingContext *aRenderingContext) { - nsGfxScrollFrameInner::ScrollbarStyles ss = GetScrollbarStyles(); + ScrollbarStyles ss = GetScrollbarStyles(); if (ss.mVertical != NS_STYLE_OVERFLOW_SCROLL || !mInner.mVScrollbarBox) return 0; @@ -861,7 +861,7 @@ nsHTMLScrollFrame::AccessibleType() // Create an accessible regardless of focusable state because the state can be // changed during frame life cycle without any notifications to accessibility. if (mContent->IsRootOfNativeAnonymousSubtree() || - GetScrollbarStyles() == nsIScrollableFrame:: + GetScrollbarStyles() == ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) ) { return a11y::eNoType; } @@ -1080,7 +1080,7 @@ nsXULScrollFrame::GetPrefSize(nsBoxLayoutState& aState) nsSize pref = mInner.mScrolledFrame->GetPrefSize(aState); - nsGfxScrollFrameInner::ScrollbarStyles styles = GetScrollbarStyles(); + ScrollbarStyles styles = GetScrollbarStyles(); // scrolled frames don't have their own margins @@ -1113,7 +1113,7 @@ nsXULScrollFrame::GetMinSize(nsBoxLayoutState& aState) nsSize min = mInner.mScrolledFrame->GetMinSizeForScrollArea(aState); - nsGfxScrollFrameInner::ScrollbarStyles styles = GetScrollbarStyles(); + ScrollbarStyles styles = GetScrollbarStyles(); if (mInner.mVScrollbarBox && styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) { @@ -2342,7 +2342,7 @@ static void HandleScrollPref(nsIScrollable *aScrollable, int32_t aOrientation, } } -nsGfxScrollFrameInner::ScrollbarStyles +ScrollbarStyles nsGfxScrollFrameInner::GetScrollbarStylesFromFrame() const { nsPresContext* presContext = mOuter->PresContext(); diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index b145d1a2f43..7e9b43ebfe0 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -51,8 +51,7 @@ public: nsGfxScrollFrameInner(nsContainerFrame* aOuter, bool aIsRoot); ~nsGfxScrollFrameInner(); - typedef nsIScrollableFrame::ScrollbarStyles ScrollbarStyles; - ScrollbarStyles GetScrollbarStylesFromFrame() const; + mozilla::ScrollbarStyles GetScrollbarStylesFromFrame() const; // If a child frame was added or removed on the scrollframe, // reload our child frame list. @@ -510,7 +509,7 @@ public: virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE { return mInner.GetScrolledFrame(); } - virtual nsGfxScrollFrameInner::ScrollbarStyles GetScrollbarStyles() const { + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const { return mInner.GetScrollbarStylesFromFrame(); } virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE { @@ -797,7 +796,7 @@ public: virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE { return mInner.GetScrolledFrame(); } - virtual nsGfxScrollFrameInner::ScrollbarStyles GetScrollbarStyles() const { + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const { return mInner.GetScrollbarStylesFromFrame(); } virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE { diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index c7503ef0bec..25f79bb667d 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -10,9 +10,8 @@ #ifndef nsIScrollFrame_h___ #define nsIScrollFrame_h___ -#include "nsISupports.h" #include "nsCoord.h" -#include "nsPresContext.h" +#include "ScrollbarStyles.h" #include "mozilla/gfx/Point.h" #include "nsIScrollbarOwner.h" #include "Units.h" @@ -23,6 +22,8 @@ class nsBoxLayoutState; class nsIScrollPositionListener; class nsIFrame; +class nsPresContext; +class nsIContent; /** * Interface for frames that are scrollable. This interface exposes @@ -41,13 +42,12 @@ public: */ virtual nsIFrame* GetScrolledFrame() const = 0; - typedef nsPresContext::ScrollbarStyles ScrollbarStyles; /** * Get the styles (NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN, * or NS_STYLE_OVERFLOW_AUTO) governing the horizontal and vertical * scrollbars for this frame. */ - virtual ScrollbarStyles GetScrollbarStyles() const = 0; + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const = 0; enum { HORIZONTAL = 0x01, VERTICAL = 0x02 }; /** diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 9a6f795f6ff..c4b87f3c100 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -338,7 +338,7 @@ CommonElementAnimationData::CanThrottleTransformChanges(TimeStamp aTime) return true; } - nsPresContext::ScrollbarStyles ss = scrollable->GetScrollbarStyles(); + ScrollbarStyles ss = scrollable->GetScrollbarStyles(); if (ss.mVertical == NS_STYLE_OVERFLOW_HIDDEN && ss.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN && scrollable->GetLogicalScrollPosition() == nsPoint(0, 0)) { diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 7a075804307..d59efcb4f5e 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -246,7 +246,7 @@ static nsSize CalcViewportUnitsScale(nsPresContext* aPresContext) nsIScrollableFrame* scrollFrame = aPresContext->PresShell()->GetRootScrollFrameAsScrollable(); if (scrollFrame) { - nsPresContext::ScrollbarStyles styles(scrollFrame->GetScrollbarStyles()); + ScrollbarStyles styles(scrollFrame->GetScrollbarStyles()); if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL || styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) { From b10afc28f0dbeb7bfed3ba37206eaefb00a9ca06 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Fri, 23 Aug 2013 13:29:01 +0200 Subject: [PATCH 08/87] Bug 905370 - Move SelfHostedClass list to JSRuntime. r=bhackett,shu --HG-- extra : rebase_source : e45e182038fdc5267aa9b50853eefb43c7f9cf54 --- js/src/vm/Runtime.cpp | 1 + js/src/vm/Runtime.h | 6 ++++++ js/src/vm/SelfHosting.cpp | 33 +++++++++++++++++---------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 1cc5030aa14..6220097f285 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -128,6 +128,7 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads) bumpAlloc_(NULL), ionRuntime_(NULL), selfHostingGlobal_(NULL), + selfHostedClasses_(NULL), nativeStackBase(0), nativeStackQuota(0), cxCallback(NULL), diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 350e1edc91c..504e6f27e21 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -663,6 +663,7 @@ typedef Vector ZoneVector; class AutoLockForExclusiveAccess; class AutoPauseWorkersForGC; +struct SelfHostedClass; class ThreadDataIter; } // namespace js @@ -853,6 +854,7 @@ struct JSRuntime : public JS::shadow::Runtime, js::ion::IonRuntime *ionRuntime_; JSObject *selfHostingGlobal_; + js::SelfHostedClass *selfHostedClasses_; /* Space for interpreter frames. */ js::InterpreterStack interpreterStack_; @@ -898,6 +900,10 @@ struct JSRuntime : public JS::shadow::Runtime, bool isSelfHostingGlobal(js::HandleObject global) { return global == selfHostingGlobal_; } + js::SelfHostedClass *selfHostedClasses() { + return selfHostedClasses_; + } + void addSelfHostedClass(js::SelfHostedClass *shClass); bool cloneSelfHostedFunctionScript(JSContext *cx, js::Handle name, js::Handle targetFun); bool cloneSelfHostedValue(JSContext *cx, js::Handle name, diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index c33c1d89155..3b950e26e1a 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -35,9 +35,6 @@ namespace js { */ struct SelfHostedClass { - /* The head of the linked list. */ - static SelfHostedClass *head; - /* Next class in the list. */ SelfHostedClass *next; @@ -50,15 +47,13 @@ struct SelfHostedClass */ static JSObject *newPrototype(JSContext *cx, uint32_t numSlots); - static bool is(Class *clasp); + static bool is(JSContext *cx, Class *clasp); SelfHostedClass(const char *name, uint32_t numSlots); }; } /* namespace js */ -SelfHostedClass *SelfHostedClass::head = NULL; - JSObject * SelfHostedClass::newPrototype(JSContext *cx, uint32_t numSlots) { @@ -66,8 +61,7 @@ SelfHostedClass::newPrototype(JSContext *cx, uint32_t numSlots) SelfHostedClass *shClass = cx->new_("Self-hosted Class", numSlots); if (!shClass) return NULL; - shClass->next = head; - head = shClass; + cx->runtime()->addSelfHostedClass(shClass); Rooted global(cx, cx->global()); RootedObject proto(cx, global->createBlankPrototype(cx, &shClass->class_)); @@ -78,9 +72,9 @@ SelfHostedClass::newPrototype(JSContext *cx, uint32_t numSlots) } bool -SelfHostedClass::is(Class *clasp) +SelfHostedClass::is(JSContext *cx, Class *clasp) { - SelfHostedClass *shClass = head; + SelfHostedClass *shClass = cx->runtime()->selfHostedClasses(); while (shClass) { if (clasp == &shClass->class_) return true; @@ -771,13 +765,13 @@ JSRuntime::finishSelfHosting() { selfHostingGlobal_ = NULL; - SelfHostedClass *head = SelfHostedClass::head; - while (head) { - SelfHostedClass *tmp = head; - head = head->next; + SelfHostedClass *shClass = selfHostedClasses_; + while (shClass) { + SelfHostedClass *tmp = shClass; + shClass = shClass->next; js_delete(tmp); } - SelfHostedClass::head = NULL; + selfHostedClasses_ = NULL; } void @@ -787,6 +781,13 @@ JSRuntime::markSelfHostingGlobal(JSTracer *trc) MarkObjectRoot(trc, &selfHostingGlobal_, "self-hosting global"); } +void +JSRuntime::addSelfHostedClass(SelfHostedClass *shClass) +{ + shClass->next = selfHostedClasses_; + selfHostedClasses_ = shClass; +} + typedef AutoObjectObjectHashMap CloneMemory; static bool CloneValue(JSContext *cx, MutableHandleValue vp, CloneMemory &clonedObjects); @@ -818,7 +819,7 @@ CloneProperties(JSContext *cx, HandleObject obj, HandleObject clone, CloneMemory } } - if (SelfHostedClass::is(obj->getClass())) { + if (SelfHostedClass::is(cx, obj->getClass())) { for (uint32_t i = 0; i < JSCLASS_RESERVED_SLOTS(obj->getClass()); i++) { val = obj->getReservedSlot(i); if (!CloneValue(cx, &val, clonedObjects)) From 5230df7601c10a4d2b0f43f763098624bde2a2c9 Mon Sep 17 00:00:00 2001 From: Joel Maher Date: Fri, 23 Aug 2013 16:40:05 -0400 Subject: [PATCH 09/87] Bug 908853 - update talos.json to include new TART test. r=avih --- testing/talos/talos.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 12b6ffa3aa0..60efbc7140d 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -5,7 +5,7 @@ }, "global": { "talos_repo": "http://hg.mozilla.org/build/talos", - "talos_revision": "2a32cc64e7ff" + "talos_revision": "1817a7d17991" }, "suites": { "chromez": { @@ -51,7 +51,7 @@ ] }, "svgr": { - "tests": ["tsvgx", "tsvgr_opacity"], + "tests": ["tsvgx", "tsvgr_opacity", "tart"], "talos_options": [ "--filter", "ignore_first:5", From df93b43bebd3ea0a4fe259eb9e9779bdcf5d987c Mon Sep 17 00:00:00 2001 From: Guillaume Abadie Date: Fri, 23 Aug 2013 16:41:46 -0400 Subject: [PATCH 10/87] bug 908662 - [WebGL 2.0] refactor WebIDL - r=jgilbert --- dom/webidl/WebGL2RenderingContext.webidl | 139 +++++++++++++---------- 1 file changed, 77 insertions(+), 62 deletions(-) diff --git a/dom/webidl/WebGL2RenderingContext.webidl b/dom/webidl/WebGL2RenderingContext.webidl index 5851ac49a7f..6d2f4a97a02 100644 --- a/dom/webidl/WebGL2RenderingContext.webidl +++ b/dom/webidl/WebGL2RenderingContext.webidl @@ -14,94 +14,109 @@ interface WebGLQuery { interface WebGL2RenderingContext : WebGLRenderingContext { /* draw buffers */ - const GLenum COLOR_ATTACHMENT1 = 0x8CE1; - const GLenum COLOR_ATTACHMENT2 = 0x8CE2; - const GLenum COLOR_ATTACHMENT3 = 0x8CE3; - const GLenum COLOR_ATTACHMENT4 = 0x8CE4; - const GLenum COLOR_ATTACHMENT5 = 0x8CE5; - const GLenum COLOR_ATTACHMENT6 = 0x8CE6; - const GLenum COLOR_ATTACHMENT7 = 0x8CE7; - const GLenum COLOR_ATTACHMENT8 = 0x8CE8; - const GLenum COLOR_ATTACHMENT9 = 0x8CE9; - const GLenum COLOR_ATTACHMENT10 = 0x8CEA; - const GLenum COLOR_ATTACHMENT11 = 0x8CEB; - const GLenum COLOR_ATTACHMENT12 = 0x8CEC; - const GLenum COLOR_ATTACHMENT13 = 0x8CED; - const GLenum COLOR_ATTACHMENT14 = 0x8CEE; - const GLenum COLOR_ATTACHMENT15 = 0x8CEF; + const GLenum COLOR_ATTACHMENT1 = 0x8CE1; + const GLenum COLOR_ATTACHMENT2 = 0x8CE2; + const GLenum COLOR_ATTACHMENT3 = 0x8CE3; + const GLenum COLOR_ATTACHMENT4 = 0x8CE4; + const GLenum COLOR_ATTACHMENT5 = 0x8CE5; + const GLenum COLOR_ATTACHMENT6 = 0x8CE6; + const GLenum COLOR_ATTACHMENT7 = 0x8CE7; + const GLenum COLOR_ATTACHMENT8 = 0x8CE8; + const GLenum COLOR_ATTACHMENT9 = 0x8CE9; + const GLenum COLOR_ATTACHMENT10 = 0x8CEA; + const GLenum COLOR_ATTACHMENT11 = 0x8CEB; + const GLenum COLOR_ATTACHMENT12 = 0x8CEC; + const GLenum COLOR_ATTACHMENT13 = 0x8CED; + const GLenum COLOR_ATTACHMENT14 = 0x8CEE; + const GLenum COLOR_ATTACHMENT15 = 0x8CEF; - const GLenum DRAW_BUFFER0 = 0x8825; - const GLenum DRAW_BUFFER1 = 0x8826; - const GLenum DRAW_BUFFER2 = 0x8827; - const GLenum DRAW_BUFFER3 = 0x8828; - const GLenum DRAW_BUFFER4 = 0x8829; - const GLenum DRAW_BUFFER5 = 0x882A; - const GLenum DRAW_BUFFER6 = 0x882B; - const GLenum DRAW_BUFFER7 = 0x882C; - const GLenum DRAW_BUFFER8 = 0x882D; - const GLenum DRAW_BUFFER9 = 0x882E; - const GLenum DRAW_BUFFER10 = 0x882F; - const GLenum DRAW_BUFFER11 = 0x8830; - const GLenum DRAW_BUFFER12 = 0x8831; - const GLenum DRAW_BUFFER13 = 0x8832; - const GLenum DRAW_BUFFER14 = 0x8833; - const GLenum DRAW_BUFFER15 = 0x8834; + const GLenum DRAW_BUFFER0 = 0x8825; + const GLenum DRAW_BUFFER1 = 0x8826; + const GLenum DRAW_BUFFER2 = 0x8827; + const GLenum DRAW_BUFFER3 = 0x8828; + const GLenum DRAW_BUFFER4 = 0x8829; + const GLenum DRAW_BUFFER5 = 0x882A; + const GLenum DRAW_BUFFER6 = 0x882B; + const GLenum DRAW_BUFFER7 = 0x882C; + const GLenum DRAW_BUFFER8 = 0x882D; + const GLenum DRAW_BUFFER9 = 0x882E; + const GLenum DRAW_BUFFER10 = 0x882F; + const GLenum DRAW_BUFFER11 = 0x8830; + const GLenum DRAW_BUFFER12 = 0x8831; + const GLenum DRAW_BUFFER13 = 0x8832; + const GLenum DRAW_BUFFER14 = 0x8833; + const GLenum DRAW_BUFFER15 = 0x8834; - const GLenum MAX_COLOR_ATTACHMENTS = 0x8CDF; - const GLenum MAX_DRAW_BUFFERS = 0x8824; + const GLenum MAX_COLOR_ATTACHMENTS = 0x8CDF; + const GLenum MAX_DRAW_BUFFERS = 0x8824; - /* vertex array objects */ - const GLenum VERTEX_ARRAY_BINDING = 0x85B5; + void drawBuffers(sequence buffers); - /* blend equations */ - const GLenum MIN = 0x8007; - const GLenum MAX = 0x8008; - /* query objects */ - const GLenum ANY_SAMPLES_PASSED = 0x8C2F; - const GLenum ANY_SAMPLES_PASSED_CONSERVATIVE = 0x8D6A; - const GLenum CURRENT_QUERY = 0x8865; - const GLenum QUERY_RESULT = 0x8866; - const GLenum QUERY_RESULT_AVAILABLE = 0x8867; + /* draw instanced */ + void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount); + void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei primcount); + /* instanced array */ - const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88FE; + const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88FE; void vertexAttribDivisor(GLuint index, GLuint divisor); + + /* blend equations */ + const GLenum MIN = 0x8007; + const GLenum MAX = 0x8008; + + /* transform feedback */ - const GLenum RASTERIZER_DISCARD = 0x8C89; - const GLenum TRANSFORM_FEEDBACK_BUFFER = 0x8C8E; - const GLenum TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F; - const GLenum TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84; - const GLenum TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85; - const GLenum MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B; + const GLenum RASTERIZER_DISCARD = 0x8C89; + const GLenum TRANSFORM_FEEDBACK_BUFFER = 0x8C8E; + const GLenum TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F; + const GLenum TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84; + const GLenum TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85; + const GLenum MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B; + + + /* query objects */ + const GLenum CURRENT_QUERY = 0x8865; + const GLenum QUERY_RESULT = 0x8866; + const GLenum QUERY_RESULT_AVAILABLE = 0x8867; + + void beginQuery(GLenum target, WebGLQuery? queryObject); + WebGLQuery? createQuery(); + void deleteQuery(WebGLQuery? queryObject); + void endQuery(GLenum target); + WebGLQuery? getQuery(GLenum target, GLenum pname); + any getQueryObject(WebGLQuery? queryObject, GLenum pname); + [WebGLHandlesContextLoss] GLboolean isQuery(WebGLQuery? queryObject); + + + /* occlusion queries */ + const GLenum ANY_SAMPLES_PASSED = 0x8C2F; + const GLenum ANY_SAMPLES_PASSED_CONSERVATIVE = 0x8D6A; + /* transform feedback queries */ - const GLenum TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 0x8C88; + const GLenum TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 0x8C88; + /* buffer objects */ void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer); void bindBufferRange(GLenum target, GLuint index, WebGLBuffer? buffer, GLintptr offset, GLsizeiptr size); + /* state requests */ any getParameterIndexed(GLenum pname, GLuint index); - void beginQuery(GLenum target, WebGLQuery? queryObject); + /* vertex array objects */ + const GLenum VERTEX_ARRAY_BINDING = 0x85B5; + void bindVertexArray(WebGLVertexArray? arrayObject); - WebGLQuery? createQuery(); WebGLVertexArray? createVertexArray(); - void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount); - void drawBuffers(sequence buffers); - void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei primcount); - void deleteQuery(WebGLQuery? queryObject); void deleteVertexArray(WebGLVertexArray? arrayObject); - void endQuery(GLenum target); - WebGLQuery? getQuery(GLenum target, GLenum pname); - any getQueryObject(WebGLQuery? queryObject, GLenum pname); - [WebGLHandlesContextLoss] GLboolean isQuery(WebGLQuery? queryObject); [WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArray? arrayObject); }; From 2d782339faba20e30df69e9f22f6af8dbb336bfc Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 18:15:45 -0400 Subject: [PATCH 11/87] Bug 908778 - Don't #include nsIContent.h in nsIFrame.h; r=mats --- layout/generic/nsFrame.cpp | 7 +++++++ layout/generic/nsIFrame.h | 7 ++----- layout/style/nsStyleStructInlines.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e92b398d434..36d2cd3d3ab 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -8113,6 +8113,13 @@ nsIFrame::CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, } } +bool +nsIFrame::IsSelected() const +{ + return (GetContent() && GetContent()->IsSelectionDescendant()) ? + IsFrameSelected() : false; +} + // Box layout debugging #ifdef DEBUG_REFLOW int32_t gIndent2 = 0; diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 628b60a35fe..d1b0ba9700a 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -28,7 +28,6 @@ #include "nsStyleStructFwd.h" #include "nsHTMLReflowMetrics.h" #include "nsFrameList.h" -#include "nsIContent.h" #include "nsAlgorithm.h" #include "mozilla/layout/FrameChildList.h" #include "FramePropertyTable.h" @@ -83,6 +82,7 @@ class gfxSkipCharsIterator; class gfxContext; class nsLineList_iterator; class nsAbsoluteContainingBlock; +class nsIContent; struct nsPeekOffsetStruct; struct nsPoint; @@ -2420,10 +2420,7 @@ public: /** * @returns true if this frame is selected. */ - bool IsSelected() const { - return (GetContent() && GetContent()->IsSelectionDescendant()) ? - IsFrameSelected() : false; - } + bool IsSelected() const; /** * called to discover where this frame, or a parent frame has user-select style diff --git a/layout/style/nsStyleStructInlines.h b/layout/style/nsStyleStructInlines.h index ba302565caa..53d2e461f01 100644 --- a/layout/style/nsStyleStructInlines.h +++ b/layout/style/nsStyleStructInlines.h @@ -15,6 +15,7 @@ #include "nsStyleStruct.h" #include "imgIRequest.h" #include "imgIContainer.h" +#include "nsIContent.h" inline void nsStyleBorder::SetBorderImage(imgRequestProxy* aImage) From 1b1e8f296f8574f448f329f62fbdd5ce8cb7401d Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 18:16:16 -0400 Subject: [PATCH 12/87] Bug 908778 - Don't #include gfxASurface.h in nsIFrame.h; r=mats --- layout/generic/nsFrame.cpp | 7 +++++++ layout/generic/nsIFrame.h | 6 +----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 36d2cd3d3ab..470368b872b 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -74,6 +74,7 @@ #include "nsRenderingContext.h" #include "nsAbsoluteContainingBlock.h" #include "nsFontInflationData.h" +#include "gfxASurface.h" #include "mozilla/Preferences.h" #include "mozilla/LookAndFeel.h" @@ -8120,6 +8121,12 @@ nsIFrame::IsSelected() const IsFrameSelected() : false; } +void +nsIFrame::DestroySurface(void* aPropertyValue) +{ + static_cast(aPropertyValue)->Release(); +} + // Box layout debugging #ifdef DEBUG_REFLOW int32_t gIndent2 = 0; diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index d1b0ba9700a..660a7c66ea0 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -36,7 +36,6 @@ #include #include "nsITheme.h" #include "gfx3DMatrix.h" -#include "gfxASurface.h" #ifdef ACCESSIBILITY #include "mozilla/a11y/AccTypes.h" @@ -893,10 +892,7 @@ public: delete static_cast(aPropertyValue); } - static void DestroySurface(void* aPropertyValue) - { - static_cast(aPropertyValue)->Release(); - } + static void DestroySurface(void* aPropertyValue); #ifdef _MSC_VER // XXX Workaround MSVC issue by making the static FramePropertyDescriptor From 9b11a8936248c01e9158a8d0f733b4085ba70295 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 18:16:38 -0400 Subject: [PATCH 13/87] Bug 908778 - Don't #include nsRegion.h in nsIFrame.h; r=mats --- layout/base/DisplayItemClip.cpp | 1 + layout/base/PositionedEventTargeting.cpp | 1 + layout/generic/nsFrame.cpp | 7 +++++++ layout/generic/nsIFrame.h | 6 +----- layout/svg/nsSVGOuterSVGFrame.h | 1 + 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/layout/base/DisplayItemClip.cpp b/layout/base/DisplayItemClip.cpp index 5a78d63c11a..09154208f64 100644 --- a/layout/base/DisplayItemClip.cpp +++ b/layout/base/DisplayItemClip.cpp @@ -9,6 +9,7 @@ #include "nsPresContext.h" #include "nsCSSRendering.h" #include "nsLayoutUtils.h" +#include "nsRegion.h" namespace mozilla { diff --git a/layout/base/PositionedEventTargeting.cpp b/layout/base/PositionedEventTargeting.cpp index d8bbd165b8d..50977290e4e 100644 --- a/layout/base/PositionedEventTargeting.cpp +++ b/layout/base/PositionedEventTargeting.cpp @@ -11,6 +11,7 @@ #include "nsEventListenerManager.h" #include "nsPrintfCString.h" #include "mozilla/dom/Element.h" +#include "nsRegion.h" #include namespace mozilla { diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 470368b872b..fcf32237a86 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -75,6 +75,7 @@ #include "nsAbsoluteContainingBlock.h" #include "nsFontInflationData.h" #include "gfxASurface.h" +#include "nsRegion.h" #include "mozilla/Preferences.h" #include "mozilla/LookAndFeel.h" @@ -8127,6 +8128,12 @@ nsIFrame::DestroySurface(void* aPropertyValue) static_cast(aPropertyValue)->Release(); } +void +nsIFrame::DestroyRegion(void* aPropertyValue) +{ + delete static_cast(aPropertyValue); +} + // Box layout debugging #ifdef DEBUG_REFLOW int32_t gIndent2 = 0; diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 660a7c66ea0..61409fd0e3f 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -22,7 +22,6 @@ #include #include "nsQueryFrame.h" -#include "nsRegion.h" #include "nsStyleContext.h" #include "nsStyleStruct.h" #include "nsStyleStructFwd.h" @@ -867,10 +866,7 @@ public: : GetPosition(); } - static void DestroyRegion(void* aPropertyValue) - { - delete static_cast(aPropertyValue); - } + static void DestroyRegion(void* aPropertyValue); static void DestroyMargin(void* aPropertyValue) { diff --git a/layout/svg/nsSVGOuterSVGFrame.h b/layout/svg/nsSVGOuterSVGFrame.h index b6a188a8caf..fc543808bbc 100644 --- a/layout/svg/nsSVGOuterSVGFrame.h +++ b/layout/svg/nsSVGOuterSVGFrame.h @@ -10,6 +10,7 @@ #include "gfxMatrix.h" #include "nsISVGSVGFrame.h" #include "nsSVGContainerFrame.h" +#include "nsRegion.h" class nsSVGForeignObjectFrame; From bf4cca3bc2d8b3a49e8f5b9aa30d179937b0d2d7 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 18:16:59 -0400 Subject: [PATCH 14/87] Bug 908778 - Don't #include nsStyleStructFwd.h in nsIFrame.h; r=mats --- layout/generic/nsIFrame.h | 1 - 1 file changed, 1 deletion(-) diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 61409fd0e3f..b17ac59dcd4 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -24,7 +24,6 @@ #include "nsQueryFrame.h" #include "nsStyleContext.h" #include "nsStyleStruct.h" -#include "nsStyleStructFwd.h" #include "nsHTMLReflowMetrics.h" #include "nsFrameList.h" #include "nsAlgorithm.h" From a40e4b39e7739f20c9fff1debae61e1e4290d732 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 18:17:19 -0400 Subject: [PATCH 15/87] Bug 908778 - Don't #include nsAlgorithm.h in nsIFrame.h; r=mats --- layout/generic/nsIFrame.h | 1 - 1 file changed, 1 deletion(-) diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index b17ac59dcd4..e0307ca55ac 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -26,7 +26,6 @@ #include "nsStyleStruct.h" #include "nsHTMLReflowMetrics.h" #include "nsFrameList.h" -#include "nsAlgorithm.h" #include "mozilla/layout/FrameChildList.h" #include "FramePropertyTable.h" #include "mozilla/TypedEnum.h" From defdf91b89b3784682526194bfbae636114ee15e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 18:18:19 -0400 Subject: [PATCH 16/87] Bug 905846 - Create Beta/Release/Common-opt mozconfigs for Win64; r=catlee --HG-- rename : browser/config/mozconfigs/win64/nightly => browser/config/mozconfigs/win64/common-opt --- browser/config/mozconfigs/win64/beta | 7 +++++++ browser/config/mozconfigs/win64/common-opt | 20 +++++++++++++++++++ browser/config/mozconfigs/win64/common-win64 | 5 +++++ browser/config/mozconfigs/win64/nightly | 21 ++------------------ browser/config/mozconfigs/win64/release | 13 ++++++++++++ 5 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 browser/config/mozconfigs/win64/beta create mode 100644 browser/config/mozconfigs/win64/common-opt create mode 100644 browser/config/mozconfigs/win64/common-win64 create mode 100644 browser/config/mozconfigs/win64/release diff --git a/browser/config/mozconfigs/win64/beta b/browser/config/mozconfigs/win64/beta new file mode 100644 index 00000000000..d3b072d6420 --- /dev/null +++ b/browser/config/mozconfigs/win64/beta @@ -0,0 +1,7 @@ +. "$topsrcdir/browser/config/mozconfigs/win64/common-opt" + +mk_add_options MOZ_PGO=1 + +ac_add_options --enable-official-branding + +. "$topsrcdir/build/mozconfig.common.override" diff --git a/browser/config/mozconfigs/win64/common-opt b/browser/config/mozconfigs/win64/common-opt new file mode 100644 index 00000000000..743bc703b2b --- /dev/null +++ b/browser/config/mozconfigs/win64/common-opt @@ -0,0 +1,20 @@ +# This file is sourced by the nightly, beta, and release mozconfigs. + +. "$topsrcdir/browser/config/mozconfigs/common" + +ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} +ac_add_options --enable-update-packaging +ac_add_options --enable-jemalloc +ac_add_options --with-google-api-keyfile=/e/builds/gapi.data + +# Needed to enable breakpad in application.ini +export MOZILLA_OFFICIAL=1 + +export MOZ_TELEMETRY_REPORTING=1 + +if test -z "${_PYMAKE}"; then + mk_add_options MOZ_MAKE_FLAGS=-j1 +fi + +# Package js shell. +export MOZ_PACKAGE_JSSHELL=1 diff --git a/browser/config/mozconfigs/win64/common-win64 b/browser/config/mozconfigs/win64/common-win64 new file mode 100644 index 00000000000..8f167cad1c5 --- /dev/null +++ b/browser/config/mozconfigs/win64/common-win64 @@ -0,0 +1,5 @@ +# This file is used by all Win64 builds + +ac_add_options --target=x86_64-pc-mingw32 +ac_add_options --host=x86_64-pc-mingw32 + diff --git a/browser/config/mozconfigs/win64/nightly b/browser/config/mozconfigs/win64/nightly index cefa49b037b..1fd63d92f2d 100644 --- a/browser/config/mozconfigs/win64/nightly +++ b/browser/config/mozconfigs/win64/nightly @@ -1,11 +1,6 @@ -. "$topsrcdir/browser/config/mozconfigs/common" +. "$topsrcdir/browser/config/mozconfigs/win64/common-win64" +. "$topsrcdir/browser/config/mozconfigs/win64/common-opt" -ac_add_options --target=x86_64-pc-mingw32 -ac_add_options --host=x86_64-pc-mingw32 - -ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} -ac_add_options --enable-update-packaging -ac_add_options --enable-jemalloc ac_add_options --enable-signmar ac_add_options --enable-profiling ac_add_options --enable-metro @@ -13,18 +8,6 @@ ac_add_options --enable-metro # Nightlies only since this has a cost in performance ac_add_options --enable-js-diagnostics -# Needed to enable breakpad in application.ini -export MOZILLA_OFFICIAL=1 - -export MOZ_TELEMETRY_REPORTING=1 - -if test -z "${_PYMAKE}"; then - mk_add_options MOZ_MAKE_FLAGS=-j1 -fi - -# Package js shell. -export MOZ_PACKAGE_JSSHELL=1 - . $topsrcdir/build/win64/mozconfig.vs2010 . "$topsrcdir/build/mozconfig.common.override" diff --git a/browser/config/mozconfigs/win64/release b/browser/config/mozconfigs/win64/release new file mode 100644 index 00000000000..c977b83f1c8 --- /dev/null +++ b/browser/config/mozconfigs/win64/release @@ -0,0 +1,13 @@ +# This make file should be identical to the beta mozconfig, apart from the +# safeguard below +. "$topsrcdir/browser/config/mozconfigs/win64/common-opt" + +mk_add_options MOZ_PGO=1 + +ac_add_options --enable-official-branding + +# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in +# defines.sh during the beta cycle +export BUILDING_RELEASE=1 + +. "$topsrcdir/build/mozconfig.common.override" From 52416f5705722fae6aaad7b21c728dd8698c47f4 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 23 Aug 2013 18:20:19 -0400 Subject: [PATCH 17/87] Bug 908746 - Move some macros from nsHTMLReflowState.h to nsIFrame.h so that we can stop #including nsHTMLReflowState.h in nsLayoutUtils.h; r=mats --- layout/base/nsLayoutUtils.h | 1 - layout/generic/nsHTMLReflowState.h | 15 --------------- layout/generic/nsIFrame.h | 15 +++++++++++++++ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index dc7bda1be73..b5ce3070db6 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -34,7 +34,6 @@ class imgIContainer; #include "nsIPrincipal.h" #include "gfxPattern.h" #include "nsCSSPseudoElements.h" -#include "nsHTMLReflowState.h" #include "FrameMetrics.h" #include "gfx3DMatrix.h" #include "nsIWidget.h" diff --git a/layout/generic/nsHTMLReflowState.h b/layout/generic/nsHTMLReflowState.h index 4bb8bf1c4f5..95ac50ae525 100644 --- a/layout/generic/nsHTMLReflowState.h +++ b/layout/generic/nsHTMLReflowState.h @@ -43,13 +43,6 @@ NS_CSS_MINMAX(NumericType aValue, NumericType aMinValue, NumericType aMaxValue) return result; } -/** - * Constant used to indicate an unconstrained size. - * - * @see #Reflow() - */ -#define NS_UNCONSTRAINEDSIZE NS_MAXSIZE - /** * CSS Frame type. Included as part of the reflow state. */ @@ -103,14 +96,6 @@ typedef uint32_t nsCSSFrameType; ((_ft) & ~(NS_CSS_FRAME_TYPE_REPLACED | \ NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK)) -#define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE -#define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE -#define NS_AUTOMARGIN NS_UNCONSTRAINEDSIZE -#define NS_AUTOOFFSET NS_UNCONSTRAINEDSIZE -// NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE -// if any are changed to be a value other than NS_UNCONSTRAINEDSIZE -// at least update AdjustComputedHeight/Width and test ad nauseum - // A base class of nsHTMLReflowState that computes only the padding, // border, and margin, since those values are needed more often. struct nsCSSOffsetState { diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index e0307ca55ac..56df0108238 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -335,6 +335,21 @@ typedef uint64_t nsFrameState; (((_frame)->GetStateBits() & \ (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0) +/** + * Constant used to indicate an unconstrained size. + * + * @see #Reflow() + */ +#define NS_UNCONSTRAINEDSIZE NS_MAXSIZE + +#define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE +#define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE +#define NS_AUTOMARGIN NS_UNCONSTRAINEDSIZE +#define NS_AUTOOFFSET NS_UNCONSTRAINEDSIZE +// NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE +// if any are changed to be a value other than NS_UNCONSTRAINEDSIZE +// at least update AdjustComputedHeight/Width and test ad nauseum + //---------------------------------------------------------------------- enum nsSelectionAmount { From a290b287b7c413b08577216826d7d5b76592de57 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 23 Aug 2013 14:39:59 -0500 Subject: [PATCH 18/87] Bug 908813 - Only report asm.js warnings once during syntax-only parse (r=bbouvier) --HG-- extra : rebase_source : be57c7ac40c828bea5577e2857b2f0709bd74a16 --- js/src/frontend/Parser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 55d9496dc3e..58233f9ee88 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -5050,6 +5050,8 @@ Parser::statement(bool canHaveDirectives) case TOK_STRING: if (!canHaveDirectives && tokenStream.currentToken().atom() == context->names().useAsm) { + if (!abortIfSyntaxParser()) + return null(); if (!report(ParseWarning, false, null(), JSMSG_USE_ASM_DIRECTIVE_FAIL)) return null(); } From fc4c03d342b0166e062d78c50f1efd00063b4d51 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Fri, 23 Aug 2013 23:23:38 +0200 Subject: [PATCH 19/87] Bug 908472 - make JSFunction::generatorKind() treat lazy self-hosted functions as non-generators. r=jwalden --HG-- extra : rebase_source : bc946eb476b6ba6dc98ea01b76c8aefc8827ddc5 --- js/src/jsfun.h | 7 ++++++- js/src/vm/SelfHosting.cpp | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 89090545969..bacbc53b3fc 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -281,7 +281,12 @@ class JSFunction : public JSObject js::GeneratorKind generatorKind() const { if (!isInterpreted()) return js::NotGenerator; - return hasScript() ? nonLazyScript()->generatorKind() : lazyScript()->generatorKind(); + if (hasScript()) + return nonLazyScript()->generatorKind(); + if (js::LazyScript *lazy = lazyScriptOrNull()) + return lazy->generatorKind(); + JS_ASSERT(isSelfHostedBuiltin()); + return js::NotGenerator; } bool isGenerator() const { return generatorKind() != js::NotGenerator; } diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 3b950e26e1a..a8590b2c9ad 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -936,6 +936,9 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, Handle na return false; RootedFunction sourceFun(cx, &funVal.toObject().as()); + // JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there + // aren't any. + JS_ASSERT(!sourceFun->isGenerator()); RootedScript sourceScript(cx, sourceFun->nonLazyScript()); JS_ASSERT(!sourceScript->enclosingStaticScope()); JSScript *cscript = CloneScript(cx, NullPtr(), targetFun, sourceScript); From 7eeb14eafbbbc31b0bcbefb6a1af65ef21595cba Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Mon, 22 Jul 2013 14:46:48 -0700 Subject: [PATCH 20/87] No bug. Remove unnecessary SkipRoot from structured clone buffers. --HG-- extra : rebase_source : 057f79cd78741572cc607213638895c2815ab7da --- js/src/vm/StructuredClone.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp index c3e1dc33b80..f2f1216d78b 100644 --- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -291,10 +291,6 @@ ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp, const JSStructuredCloneCallbacks *cb, void *cbClosure) { SCInput in(cx, data, nbytes); - - /* XXX disallow callers from using internal pointers to GC things. */ - SkipRoot skip(cx, &in); - JSStructuredCloneReader r(in, cb, cbClosure); return r.read(vp); } From e31b9e6dd01b2a29caf7a91ae937444bf0f5fe84 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Tue, 30 Jul 2013 12:36:03 -0700 Subject: [PATCH 21/87] Bug 899712 - Prevent infinite recursion in fallback asinh, r=jorendorff --HG-- extra : rebase_source : 1b810304f83b81fd435f3de3350004d0fcffba14 --- js/src/jsmath.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 67e05ccfa7a..e8f6d23a709 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -1017,7 +1017,9 @@ js::math_acosh(JSContext *cx, unsigned argc, Value *vp) } #if !HAVE_ASINH -double asinh(double x) +// Bug 899712 - gcc incorrectly rewrites -asinh(-x) to asinh(x) when overriding +// asinh. +static double my_asinh(double x) { const double SQUARE_ROOT_EPSILON = sqrt(std::numeric_limits::epsilon()); const double FOURTH_ROOT_EPSILON = sqrt(SQUARE_ROOT_EPSILON); @@ -1032,7 +1034,7 @@ double asinh(double x) else return log(x + sqrt(x * x + 1)); } else if (x <= -FOURTH_ROOT_EPSILON) { - return -asinh(-x); + return -my_asinh(-x); } else { // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/03/01/0001/ // approximation by taylor series in x at 0 up to order 2 @@ -1052,7 +1054,11 @@ double asinh(double x) double js::math_asinh_impl(MathCache *cache, double x) { +#ifdef HAVE_ASINH return cache->lookup(asinh, x); +#else + return cache->lookup(my_asinh, x); +#endif } bool From 3c32a564975ff33ffd690e2c86e5ceb120013278 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Thu, 25 Jul 2013 18:39:10 -0700 Subject: [PATCH 22/87] Bug 900144 - Add redirect shell built-in for changing stdout/stderr destination --HG-- extra : rebase_source : f6fe4aa12d0e053437044306a1815c1e32f5f153 --- js/src/shell/js.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index d8c0313eee5..1afa27669e3 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3371,6 +3371,52 @@ ReadRelativeToScript(JSContext *cx, unsigned argc, jsval *vp) return ReadFile(cx, argc, vp, true); } +static bool +redirect(JSContext *cx, FILE* fp, HandleString relFilename) +{ + RootedString filename(cx, ResolvePath(cx, relFilename, false)); + if (!filename) + return false; + JSAutoByteString filenameABS(cx, filename); + if (!filenameABS) + return false; + if (freopen(filenameABS.ptr(), "wb", fp) == NULL) { + JS_ReportError(cx, "cannot redirect to %s: %s", filenameABS.ptr(), strerror(errno)); + return false; + } + return true; +} + +static bool +RedirectOutput(JSContext *cx, unsigned argc, jsval *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() < 1 || args.length() > 2) { + JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "redirect"); + return false; + } + + if (args[0].isString()) { + RootedString stdoutPath(cx, args[0].toString()); + if (!stdoutPath) + return false; + if (!redirect(cx, stdout, stdoutPath)) + return false; + } + + if (args.length() > 1 && args[1].isString()) { + RootedString stderrPath(cx, args[1].toString()); + if (!stderrPath) + return false; + if (!redirect(cx, stderr, stderrPath)) + return false; + } + + args.rval().setUndefined(); + return true; +} + static bool System(JSContext *cx, unsigned argc, jsval *vp) { @@ -3861,7 +3907,12 @@ static const JSFunctionSpecWithHelp shell_functions[] = { JS_FN_HELP("readRelativeToScript", ReadRelativeToScript, 1, 0, "readRelativeToScript(filename, [\"binary\"])", " Read filename into returned string. Filename is relative to the directory\n" - " containing the current script."), +" containing the current script."), + + JS_FN_HELP("redirect", RedirectOutput, 2, 0, +"redirect(stdoutFilename[, stderrFilename])", +" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n" +" redirecting. Filenames are relative to the current working directory."), JS_FN_HELP("compile", Compile, 1, 0, "compile(code)", From dd45e70ceda7dada4fbd407e55d705bbd23cfb8a Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Tue, 23 Jul 2013 12:17:07 -0700 Subject: [PATCH 23/87] Bug 908825 - Pass functionName around instead of using a global variable I just found it easier to follow what's going on this way. Also, this passes a 'suppressed' value through to functions, which might change behavior but if so I'm happy with the new behavior. --HG-- extra : rebase_source : 1ee42853de87de18f9dd17e8c2eeb6677bdf8d2c --- js/src/devtools/rootAnalysis/analyzeRoots.js | 43 ++++++++++--------- .../devtools/rootAnalysis/computeCallgraph.js | 1 + js/src/devtools/rootAnalysis/loadCallgraph.js | 4 -- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index aa80a54bdce..d46ba83e7ce 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -8,7 +8,6 @@ loadRelativeToScript('suppressedPoints.js'); var sourceRoot = (environment['SOURCE_ROOT'] || '') + '/' -var functionName; var functionBodies; if (typeof scriptArgs[0] != 'string' || typeof scriptArgs[1] != 'string') @@ -80,12 +79,15 @@ function edgeUsesVariable(edge, variable) if (ignoreEdgeUse(edge, variable)) return false; switch (edge.Kind) { + case "Assign": if (expressionUsesVariable(edge.Exp[0], variable)) return true; return expressionUsesVariable(edge.Exp[1], variable); + case "Assume": return expressionUsesVariable(edge.Exp[0], variable); + case "Call": if (expressionUsesVariable(edge.Exp[0], variable)) return true; @@ -102,8 +104,10 @@ function edgeUsesVariable(edge, variable) } } return false; + case "Loop": return false; + default: assert(false); } @@ -202,8 +206,6 @@ function edgeKillsVariable(edge, variable) function edgeCanGC(edge) { - if (functionName in suppressedFunctions) - return false; if (edge.Kind != "Call") return false; var callee = edge.Exp[0]; @@ -242,7 +244,7 @@ function computePredecessors(body) } } -function variableUseFollowsGC(variable, worklist) +function variableUseFollowsGC(suppressed, variable, worklist) { while (worklist.length) { var entry = worklist.pop(); @@ -299,7 +301,7 @@ function variableUseFollowsGC(variable, worklist) } var gcInfo = entry.gcInfo; - if (!gcInfo && !(edge.Index[0] in body.suppressed)) { + if (!gcInfo && !(edge.Index[0] in body.suppressed) && !suppressed) { var gcName = edgeCanGC(edge); if (gcName) gcInfo = {name:gcName, body:body, ppoint:source}; @@ -334,7 +336,7 @@ function variableUseFollowsGC(variable, worklist) return null; } -function variableLiveAcrossGC(variable) +function variableLiveAcrossGC(suppressed, variable) { for (var body of functionBodies) { body.seen = null; @@ -346,7 +348,7 @@ function variableLiveAcrossGC(variable) for (var edge of body.PEdge) { if (edgeUsesVariable(edge, variable) && !edgeKillsVariable(edge, variable)) { var worklist = [{body:body, ppoint:edge.Index[0], gcInfo:null, why:null}]; - var call = variableUseFollowsGC(variable, worklist); + var call = variableUseFollowsGC(suppressed, variable, worklist); if (call) return call; } @@ -355,14 +357,14 @@ function variableLiveAcrossGC(variable) return null; } -function unsafeVariableAddressTaken(variable) +function unsafeVariableAddressTaken(suppressed, variable) { for (var body of functionBodies) { if (!("PEdge" in body)) continue; for (var edge of body.PEdge) { if (edgeTakesVariableAddress(edge, variable)) { - if (edge.Kind == "Assign" || edgeCanGC(edge)) + if (edge.Kind == "Assign" || (!suppressed && edgeCanGC(edge))) return {body:body, ppoint:edge.Index[0]}; } } @@ -370,7 +372,7 @@ function unsafeVariableAddressTaken(variable) return null; } -function computePrintedLines() +function computePrintedLines(functionName) { assert(!system("xdbfind src_body.xdb '" + functionName + "' > " + tmpfile)); var lines = snarf(tmpfile).split('\n'); @@ -422,10 +424,10 @@ function locationLine(text) return 0; } -function printEntryTrace(entry) +function printEntryTrace(functionName, entry) { if (!functionBodies[0].lines) - computePrintedLines(); + computePrintedLines(functionName); while (entry) { var ppoint = entry.ppoint; @@ -481,10 +483,11 @@ function typeDesc(type) } } -function processBodies() +function processBodies(functionName) { if (!("DefineVariable" in functionBodies[0])) return; + var suppressed = (functionName in suppressedFunctions); for (var variable of functionBodies[0].DefineVariable) { if (variable.Variable.Kind == "Return") continue; @@ -494,7 +497,7 @@ function processBodies() else name = variable.Variable.Name[0]; if (isRootedType(variable.Type)) { - if (!variableLiveAcrossGC(variable.Variable)) { + if (!variableLiveAcrossGC(suppressed, variable.Variable)) { // The earliest use of the variable should be its constructor. var lineText; for (var body of functionBodies) { @@ -508,7 +511,7 @@ function processBodies() " has unnecessary root '" + name + "' at " + lineText); } } else if (isUnrootedType(variable.Type)) { - var result = variableLiveAcrossGC(variable.Variable); + var result = variableLiveAcrossGC(suppressed, variable.Variable); if (result) { var lineText = findLocation(result.gcInfo.body, result.gcInfo.ppoint); print("\nFunction '" + functionName + "'" + @@ -516,15 +519,15 @@ function processBodies() " of type '" + typeDesc(variable.Type) + "'" + " live across GC call " + result.gcInfo.name + " at " + lineText); - printEntryTrace(result.why); + printEntryTrace(functionName, result.why); } - result = unsafeVariableAddressTaken(variable.Variable); + result = unsafeVariableAddressTaken(suppressed, variable.Variable); if (result) { var lineText = findLocation(result.body, result.ppoint); print("\nFunction '" + functionName + "'" + " takes unsafe address of unrooted '" + name + "'" + " at " + lineText); - printEntryTrace({body:result.body, ppoint:result.ppoint}); + printEntryTrace(functionName, {body:result.body, ppoint:result.ppoint}); } } } @@ -546,7 +549,7 @@ var end = Math.min(minStream + each * batch - 1, maxStream); for (var nameIndex = start; nameIndex <= end; nameIndex++) { var name = xdb.read_key(nameIndex); - functionName = name.readString(); + var functionName = name.readString(); var data = xdb.read_entry(name); functionBodies = JSON.parse(data.readString()); @@ -554,7 +557,7 @@ for (var nameIndex = start; nameIndex <= end; nameIndex++) { body.suppressed = []; for (var body of functionBodies) computeSuppressedPoints(body); - processBodies(); + processBodies(functionName); xdb.free_string(name); xdb.free_string(data); diff --git a/js/src/devtools/rootAnalysis/computeCallgraph.js b/js/src/devtools/rootAnalysis/computeCallgraph.js index e0b7d25511c..cf239ced392 100644 --- a/js/src/devtools/rootAnalysis/computeCallgraph.js +++ b/js/src/devtools/rootAnalysis/computeCallgraph.js @@ -25,6 +25,7 @@ function addClassEntry(index, name, other) index[name].push(other); } +// CSU is "Class/Struct/Union" function processCSU(csuName, csu) { if (!("FunctionField" in csu)) diff --git a/js/src/devtools/rootAnalysis/loadCallgraph.js b/js/src/devtools/rootAnalysis/loadCallgraph.js index 263478d4151..b75bdf92d9e 100644 --- a/js/src/devtools/rootAnalysis/loadCallgraph.js +++ b/js/src/devtools/rootAnalysis/loadCallgraph.js @@ -102,10 +102,6 @@ function loadCallgraph(file) for (var gcName of [ 'jsgc.cpp:void Collect(JSRuntime*, uint8, int64, uint32, uint32)', 'void js::MinorGC(JSRuntime*, uint32)' ]) { - if (!callerGraph[gcName]) { - debugger; - print(callerGraph) - } assert(gcName in callerGraph); addGCFunction(gcName, "GC"); } From a8863e16d584f4f234b2208048fddddc632d03c1 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Fri, 26 Jul 2013 10:40:36 -0700 Subject: [PATCH 24/87] Bug 908825 - Minor irrelevant cleanups to static rooting analysis --HG-- extra : rebase_source : 63c13fc6817fc14b2c47357bf213d7a6615f1f35 --- js/src/devtools/rootAnalysis/analyzeRoots.js | 24 +++++--- js/src/devtools/rootAnalysis/loadCallgraph.js | 58 +++++++++---------- .../devtools/rootAnalysis/suppressedPoints.js | 1 + js/src/devtools/rootAnalysis/utility.js | 11 +++- 4 files changed, 54 insertions(+), 40 deletions(-) diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index d46ba83e7ce..979c947435d 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -21,14 +21,14 @@ var numBatches = (scriptArgs[4]|0) || 1; var tmpfile = scriptArgs[5] || "tmp.txt"; var gcFunctions = {}; -var text = snarf("gcFunctions.lst").split('\n'); +var text = snarf("gcFunctions.lst").split("\n"); assert(text.pop().length == 0); for (var line of text) { gcFunctions[line] = true; } var suppressedFunctions = {}; -var text = snarf("suppressedFunctions.lst").split('\n'); +var text = snarf(suppressedFunctionsFile).split("\n"); assert(text.pop().length == 0); for (var line of text) { suppressedFunctions[line] = true; @@ -39,14 +39,14 @@ var match; var gcThings = {}; var gcPointers = {}; -var gcTypesText = snarf(gcTypesFile).split('\n'); -for (var line of gcTypesText) { +text = snarf(gcTypesFile).split("\n"); +for (var line of text) { if (match = /GCThing: (.*)/.exec(line)) gcThings[match[1]] = true; if (match = /GCPointer: (.*)/.exec(line)) gcPointers[match[1]] = true; } -gcTypesText = null; +text = null; function isUnrootedType(type) { @@ -246,6 +246,10 @@ function computePredecessors(body) function variableUseFollowsGC(suppressed, variable, worklist) { + // Scan through all edges following an unrooted variable use, using an + // explicit worklist. A worklist contains a following edge together with a + // description of where one of its predecessors GC'd (if any). + while (worklist.length) { var entry = worklist.pop(); var body = entry.body, ppoint = entry.ppoint; @@ -263,7 +267,7 @@ function variableUseFollowsGC(suppressed, variable, worklist) if (ppoint == body.Index[0]) { if (body.BlockId.Kind == "Loop") { - // propagate to parents which enter the loop body. + // propagate to parents that enter the loop body. if ("BlockPPoint" in body) { for (var parent of body.BlockPPoint) { var found = false; @@ -301,8 +305,8 @@ function variableUseFollowsGC(suppressed, variable, worklist) } var gcInfo = entry.gcInfo; - if (!gcInfo && !(edge.Index[0] in body.suppressed) && !suppressed) { - var gcName = edgeCanGC(edge); + if (!gcInfo && !(source in body.suppressed) && !suppressed) { + var gcName = edgeCanGC(edge, body); if (gcName) gcInfo = {name:gcName, body:body, ppoint:source}; } @@ -338,10 +342,14 @@ function variableUseFollowsGC(suppressed, variable, worklist) function variableLiveAcrossGC(suppressed, variable) { + // A variable is live across a GC if (1) it is used by an edge, and (2) it + // is used after a GC in a successor edge. + for (var body of functionBodies) { body.seen = null; body.minimumUse = 0; } + for (var body of functionBodies) { if (!("PEdge" in body)) continue; diff --git a/js/src/devtools/rootAnalysis/loadCallgraph.js b/js/src/devtools/rootAnalysis/loadCallgraph.js index b75bdf92d9e..847cb57e627 100644 --- a/js/src/devtools/rootAnalysis/loadCallgraph.js +++ b/js/src/devtools/rootAnalysis/loadCallgraph.js @@ -40,62 +40,62 @@ function loadCallgraph(file) { var textLines = snarf(file).split('\n'); for (var line of textLines) { - var match; + var match; if (match = /^\#(\d+) (.*)/.exec(line)) { assert(functionNames.length == match[1]); functionNames.push(match[2]); continue; } - var suppressed = false; - if (/SUPPRESS_GC/.test(line)) { + var suppressed = false; + if (/SUPPRESS_GC/.test(line)) { match = /^(..)SUPPRESS_GC (.*)/.exec(line); line = match[1] + match[2]; suppressed = true; - } - if (match = /^I (\d+) VARIABLE ([^\,]*)/.exec(line)) { + } + if (match = /^I (\d+) VARIABLE ([^\,]*)/.exec(line)) { var caller = functionNames[match[1]]; var name = match[2]; if (!indirectCallCannotGC(caller, name) && !suppressed) - addGCFunction(caller, "IndirectCall: " + name); - } else if (match = /^F (\d+) CLASS (.*?) FIELD (.*)/.exec(line)) { + addGCFunction(caller, "IndirectCall: " + name); + } else if (match = /^F (\d+) CLASS (.*?) FIELD (.*)/.exec(line)) { var caller = functionNames[match[1]]; var csu = match[2]; var fullfield = csu + "." + match[3]; if (!fieldCallCannotGC(csu, fullfield) && !suppressed) - addGCFunction(caller, "FieldCall: " + fullfield); - } else if (match = /^D (\d+) (\d+)/.exec(line)) { + addGCFunction(caller, "FieldCall: " + fullfield); + } else if (match = /^D (\d+) (\d+)/.exec(line)) { var caller = functionNames[match[1]]; var callee = functionNames[match[2]]; addCallEdge(caller, callee, suppressed); - } + } } var worklist = []; for (var name in callerGraph) - suppressedFunctions[name] = true; + suppressedFunctions[name] = true; for (var name in calleeGraph) { - if (!(name in callerGraph)) { + if (!(name in callerGraph)) { suppressedFunctions[name] = true; worklist.push(name); - } + } } while (worklist.length) { - name = worklist.pop(); - if (shouldSuppressGC(name)) + name = worklist.pop(); + if (shouldSuppressGC(name)) continue; - if (!(name in suppressedFunctions)) + if (!(name in suppressedFunctions)) continue; - delete suppressedFunctions[name]; - if (!(name in calleeGraph)) + delete suppressedFunctions[name]; + if (!(name in calleeGraph)) continue; - for (var entry of calleeGraph[name]) { + for (var entry of calleeGraph[name]) { if (!entry.suppressed) - worklist.push(entry.callee); - } + worklist.push(entry.callee); + } } for (var name in gcFunctions) { - if (name in suppressedFunctions) + if (name in suppressedFunctions) delete gcFunctions[name]; } @@ -108,16 +108,16 @@ function loadCallgraph(file) var worklist = []; for (var name in gcFunctions) - worklist.push(name); + worklist.push(name); while (worklist.length) { - name = worklist.pop(); - assert(name in gcFunctions); - if (!(name in callerGraph)) + name = worklist.pop(); + assert(name in gcFunctions); + if (!(name in callerGraph)) continue; - for (var entry of callerGraph[name]) { + for (var entry of callerGraph[name]) { if (!entry.suppressed && addGCFunction(entry.caller, name)) - worklist.push(entry.caller); - } + worklist.push(entry.caller); + } } } diff --git a/js/src/devtools/rootAnalysis/suppressedPoints.js b/js/src/devtools/rootAnalysis/suppressedPoints.js index 34a13f308fe..ddf749aeb1c 100644 --- a/js/src/devtools/rootAnalysis/suppressedPoints.js +++ b/js/src/devtools/rootAnalysis/suppressedPoints.js @@ -53,6 +53,7 @@ function computeSuppressedPoints(body) if (!("PEdge" in body)) return; + for (var edge of body.PEdge) { var source = edge.Index[0]; if (!(source in successors)) diff --git a/js/src/devtools/rootAnalysis/utility.js b/js/src/devtools/rootAnalysis/utility.js index 23457e356e3..b74eb263d1e 100644 --- a/js/src/devtools/rootAnalysis/utility.js +++ b/js/src/devtools/rootAnalysis/utility.js @@ -2,9 +2,14 @@ "use strict"; -function assert(x) +function assert(x, msg) { - if (!x) + if (x) + return; + debugger; + if (msg) + throw "assertion failed: " + msg + "\n" + (Error().stack); + else throw "assertion failed: " + (Error().stack); } @@ -45,7 +50,7 @@ function sameVariable(var0, var1) assert("Name" in var0 || var0.Kind == "This" || var0.Kind == "Return"); assert("Name" in var1 || var1.Kind == "This" || var1.Kind == "Return"); if ("Name" in var0) - return "Name" in var1 && var0.Name[0] == var1.Name[0]; + return "Name" in var1 && var0.Name[0] == var1.Name[0]; return var0.Kind == var1.Kind; } From ef73a322e1e95ad2bc1394d0ba017d5d75107336 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Thu, 1 Aug 2013 14:59:09 -0700 Subject: [PATCH 25/87] Bug 908825 - Generate multiple output files from intermediate rooting analysis stages --HG-- extra : rebase_source : b90f85cfd1815d9a7fea4792b965b8a434f5fa6e --- js/src/devtools/rootAnalysis/analyze.py | 114 +++++++++++++----- js/src/devtools/rootAnalysis/analyzeRoots.js | 24 +++- .../rootAnalysis/computeGCFunctions.js | 45 ++++++- js/src/devtools/rootAnalysis/loadCallgraph.js | 1 + 4 files changed, 144 insertions(+), 40 deletions(-) diff --git a/js/src/devtools/rootAnalysis/analyze.py b/js/src/devtools/rootAnalysis/analyze.py index 4a8956e547e..fbe88b694ee 100755 --- a/js/src/devtools/rootAnalysis/analyze.py +++ b/js/src/devtools/rootAnalysis/analyze.py @@ -14,12 +14,15 @@ import subprocess import os import argparse import sys +import re def env(config): - e = os.environ + e = dict(os.environ) e['PATH'] = '%s:%s/bin' % (e['PATH'], config['sixgill']) e['XDB'] = '%(sixgill)s/bin/xdb.so' % config - e['SOURCE_ROOT'] = config['source'] or e['TARGET'] + e['SOURCE_ROOT'] = config['source'] or e.get('TARGET', '') + e['TARGET_OBJ'] = config['objdir'] + e['TARGET'] = config['source'] return e def fill(command, config): @@ -27,12 +30,13 @@ def fill(command, config): return tuple(s % config for s in command) except: print("Substitution failed:") + problems = [] for fragment in command: try: fragment % config except: - print(" %s" % fragment) - raise Hell + problems.append(fragment) + raise Exception("\n".join(["Substitution failed:"] + [ " %s" % s for s in problems ])) def print_command(command, outfile=None, env=None): output = ' '.join(command) @@ -45,7 +49,19 @@ def print_command(command, outfile=None, env=None): if (key not in e) or (e[key] != value): changed[key] = value if changed: - output = ' '.join(key + "='" + value + "'" for key, value in changed.items()) + ' ' + output + outputs = [] + for key, value in changed.items(): + if key in e and e[key] in value: + start = value.index(e[key]) + end = start + len(e[key]) + outputs.append('%s="%s${%s}%s"' % (key, + value[:start], + key, + value[end:])) + else: + outputs.append("%s='%s'" % (key, value)) + output = ' '.join(outputs) + " " + output + print output def generate_hazards(config, outfilename): @@ -54,6 +70,7 @@ def generate_hazards(config, outfilename): command = fill(('%(js)s', '%(analysis_scriptdir)s/analyzeRoots.js', '%(gcFunctions_list)s', + '%(gcEdges)s', '%(suppressedFunctions_list)s', '%(gcTypes)s', str(i+1), '%(jobs)s', @@ -86,23 +103,16 @@ JOBS = { 'dbs': '-b', '%(sixgill)s/bin', '--buildcommand=%(buildcommand)s', '.'), - None), + ()), 'callgraph': (('%(js)s', '%(analysis_scriptdir)s/computeCallgraph.js'), 'callgraph.txt'), 'gcFunctions': - (('%(js)s', '%(analysis_scriptdir)s/computeGCFunctions.js', '%(callgraph)s'), - 'gcFunctions.txt'), - - 'gcFunctions_list': - (('perl', '-lne', 'print $1 if /^GC Function: (.*)/', '%(gcFunctions)s'), - 'gcFunctions.lst'), - - 'suppressedFunctions_list': - (('perl', '-lne', 'print $1 if /^Suppressed Function: (.*)/', '%(gcFunctions)s'), - 'suppressedFunctions.lst'), + (('%(js)s', '%(analysis_scriptdir)s/computeGCFunctions.js', '%(callgraph)s', + '[gcFunctions]', '[gcFunctions_list]', '[gcEdges]', '[suppressedFunctions_list]'), + ('gcFunctions.txt', 'gcFunctions.lst', 'gcEdges.txt', 'suppressedFunctions.lst')), 'gcTypes': (('%(js)s', '%(analysis_scriptdir)s/computeGCTypes.js',), @@ -116,19 +126,49 @@ JOBS = { 'dbs': (generate_hazards, 'rootingHazards.txt') } + +def out_indexes(command): + for i in range(len(command)): + m = re.match(r'^\[(.*)\]$', command[i]) + if m: + yield (i, m.group(1)) + + def run_job(name, config): - command, outfilename = JOBS[name] - print("Running " + name + " to generate " + str(outfilename)) - if hasattr(command, '__call__'): - command(config, outfilename) + cmdspec, outfiles = JOBS[name] + print("Running " + name + " to generate " + str(outfiles)) + if hasattr(cmdspec, '__call__'): + cmdspec(config, outfiles) else: - command = fill(command, config) + temp_map = {} + cmdspec = fill(cmdspec, config) temp = '%s.tmp' % name - print_command(command, outfile=outfilename, env=env(config)) + if isinstance(outfiles, basestring): + temp_map[temp] = outfiles + print_command(cmdspec, outfile=outfiles, env=env(config)) + else: + pc = list(cmdspec) + outfile = 0 + for (i, name) in out_indexes(cmdspec): + pc[i] = outfiles[outfile] + outfile += 1 + print_command(pc, env=env(config)) + + command = list(cmdspec) + outfile = 0 + for (i, name) in out_indexes(cmdspec): + command[i] = '%s.tmp' % name + temp_map[command[i]] = outfiles[outfile] + outfile += 1 + with open(temp, 'w') as output: subprocess.check_call(command, stdout=output, env=env(config)) - if outfilename is not None: - os.rename(temp, outfilename) + for (temp, final) in temp_map.items(): + try: + os.rename(temp, final) + except OSError: + print("Error renaming %s -> %s" % (temp, final)) + raise config = { 'CWD': os.path.dirname(__file__) } @@ -147,6 +187,8 @@ parser.add_argument('target', metavar='TARGET', type=str, nargs='?', help='run starting from this target') parser.add_argument('--source', metavar='SOURCE', type=str, nargs='?', help='source code to analyze') +parser.add_argument('--upto', metavar='UPTO', type=str, nargs='?', + help='last step to execute') parser.add_argument('--jobs', '-j', default=4, metavar='JOBS', type=int, help='number of simultaneous analyzeRoots.js jobs') parser.add_argument('--list', const=True, nargs='?', type=bool, @@ -169,12 +211,18 @@ elif 'BUILD' in os.environ: else: data['buildcommand'] = 'make -j4 -s' +if 'TARGET_OBJ' in os.environ: + data['objdir'] = os.environ['TARGET_OBJ'] + +if args.target: + data['source'] = args.target +elif 'TARGET' in os.environ: + data['source'] = os.environ['TARGET'] + targets = [ 'dbs', 'callgraph', 'gcTypes', 'gcFunctions', - 'gcFunctions_list', - 'suppressedFunctions_list', 'allFunctions', 'hazards' ] @@ -188,11 +236,21 @@ if args.list: sys.exit(0) for target in targets: - command, outfilename = JOBS[target] - data[target] = outfilename + command, outfiles = JOBS[target] + if isinstance(outfiles, basestring): + data[target] = outfiles + else: + outfile = 0 + for (i, name) in out_indexes(command): + data[name] = outfiles[outfile] + outfile += 1 + assert len(outfiles) == outfile, 'target %s: mismatched number of output files and params' % target if args.target: targets = targets[targets.index(args.target):] +if args.upto: + targets = targets[:targets.index(args.upto)+1] + for target in targets: run_job(target, data) diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index 979c947435d..0367b9d8704 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -11,14 +11,15 @@ var sourceRoot = (environment['SOURCE_ROOT'] || '') + '/' var functionBodies; if (typeof scriptArgs[0] != 'string' || typeof scriptArgs[1] != 'string') - throw "Usage: analyzeRoots.js [start end [tmpfile]]"; + throw "Usage: analyzeRoots.js [start end [tmpfile]]"; var gcFunctionsFile = scriptArgs[0]; -var suppressedFunctionsFile = scriptArgs[1]; -var gcTypesFile = scriptArgs[2]; -var batch = (scriptArgs[3]|0) || 1; -var numBatches = (scriptArgs[4]|0) || 1; -var tmpfile = scriptArgs[5] || "tmp.txt"; +var gcEdgesFile = scriptArgs[1]; +var suppressedFunctionsFile = scriptArgs[2]; +var gcTypesFile = scriptArgs[3]; +var batch = (scriptArgs[4]|0) || 1; +var numBatches = (scriptArgs[5]|0) || 1; +var tmpfile = scriptArgs[6] || "tmp.txt"; var gcFunctions = {}; var text = snarf("gcFunctions.lst").split("\n"); @@ -35,6 +36,17 @@ for (var line of text) { } text = null; +var gcEdges = {}; +text = snarf(gcEdgesFile).split('\n'); +assert(text.pop().length == 0); +for (var line of text) { + var [ block, edge, func ] = line.split(" || "); + if (!(block in gcEdges)) + gcEdges[block] = {} + gcEdges[block][edge] = func; +} +text = null; + var match; var gcThings = {}; var gcPointers = {}; diff --git a/js/src/devtools/rootAnalysis/computeGCFunctions.js b/js/src/devtools/rootAnalysis/computeGCFunctions.js index 0a8e02c0644..dbd5cf24ed3 100644 --- a/js/src/devtools/rootAnalysis/computeGCFunctions.js +++ b/js/src/devtools/rootAnalysis/computeGCFunctions.js @@ -7,12 +7,20 @@ loadRelativeToScript('annotations.js'); loadRelativeToScript('loadCallgraph.js'); if (typeof scriptArgs[0] != 'string') - throw "Usage: computeGCFunctions.js "; + throw "Usage: computeGCFunctions.js "; -print("Time: " + new Date); +var start = "Time: " + new Date; -loadCallgraph(scriptArgs[0]); +var callgraph_filename = scriptArgs[0]; +var gcFunctions_filename = scriptArgs[1] || "gcFunctions.txt"; +var gcFunctionsList_filename = scriptArgs[2] || "gcFunctions.lst"; +var gcEdges_filename = scriptArgs[3] || "gcEdges.txt"; +var suppressedFunctionsList_filename = scriptArgs[4] || "suppressedFunctions.lst"; +loadCallgraph(callgraph_filename); + +printErr("Writing " + gcFunctions_filename); +redirect(gcFunctions_filename); for (var name in gcFunctions) { print(""); print("GC Function: " + name); @@ -22,7 +30,32 @@ for (var name in gcFunctions) { } while (name in gcFunctions); } -for (var name in suppressedFunctions) { - print(""); - print("Suppressed Function: " + name); +printErr("Writing " + gcFunctionsList_filename); +redirect(gcFunctionsList_filename); +for (var name in gcFunctions) { + print(name); +} + +// gcEdges is a list of edges that can GC for more specific reasons than just +// calling a function that is in gcFunctions.txt. +// +// Right now, it is unused. It was mean for ~AutoCompartment when it might wrap +// an exception, but anything held live across ~AC will have to be held live +// across the corresponding constructor (and hence the whole scope of the AC), +// and in that case it'll be held live across whatever could create an +// exception within the AC scope. So ~AC edges are redundant. I will leave the +// stub machinery here for now. +printErr("Writing " + gcEdges_filename); +redirect(gcEdges_filename); +for (var block in gcEdges) { + for (var edge in gcEdges[block]) { + var func = gcEdges[block][edge]; + print([ block, edge, func ].join(" || ")); + } +} + +printErr("Writing " + suppressedFunctionsList_filename); +redirect(suppressedFunctionsList_filename); +for (var name in suppressedFunctions) { + print(name); } diff --git a/js/src/devtools/rootAnalysis/loadCallgraph.js b/js/src/devtools/rootAnalysis/loadCallgraph.js index 847cb57e627..013204b41cf 100644 --- a/js/src/devtools/rootAnalysis/loadCallgraph.js +++ b/js/src/devtools/rootAnalysis/loadCallgraph.js @@ -5,6 +5,7 @@ var calleeGraph = {}; var callerGraph = {}; var gcFunctions = {}; +var gcEdges = {}; var suppressedFunctions = {}; function addGCFunction(caller, reason) From 2378f796dceaf5e7c0d2e50570cadd0321827fdf Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Fri, 23 Aug 2013 13:03:23 -0700 Subject: [PATCH 26/87] Bug 908825 - Refactor static rooting analysis to make the following patch cleaner --HG-- extra : rebase_source : 52a5b477899cfd500327650448547d86e02b71eb --- js/src/devtools/rootAnalysis/analyzeRoots.js | 8 +- .../devtools/rootAnalysis/computeCallgraph.js | 113 +++++++++++------- .../devtools/rootAnalysis/suppressedPoints.js | 59 ++++----- js/src/devtools/rootAnalysis/utility.js | 49 ++++++++ 4 files changed, 148 insertions(+), 81 deletions(-) diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index 0367b9d8704..9a265bd7983 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -299,13 +299,11 @@ function variableUseFollowsGC(suppressed, variable, worklist) } } - if (!body.predecessors) - computePredecessors(body); - - if (!(ppoint in body.predecessors)) + var predecessors = getPredecessors(body); + if (!(ppoint in predecessors)) continue; - for (var edge of body.predecessors[ppoint]) { + for (var edge of predecessors[ppoint]) { var source = edge.Index[0]; if (edgeKillsVariable(edge, variable)) { diff --git a/js/src/devtools/rootAnalysis/computeCallgraph.js b/js/src/devtools/rootAnalysis/computeCallgraph.js index cf239ced392..d2a11e3149d 100644 --- a/js/src/devtools/rootAnalysis/computeCallgraph.js +++ b/js/src/devtools/rootAnalysis/computeCallgraph.js @@ -107,14 +107,72 @@ function memo(name) var seenCallees = null; var seenSuppressedCallees = null; +// Return a list of all callees that the given edge might be a call to. Each +// one is represented by an object with a 'kind' field that is one of +// ('direct', 'field', 'indirect', 'unknown'). +function getCallees(edge) +{ + if (edge.Kind != "Call") + return []; + + var callee = edge.Exp[0]; + var callees = []; + if (callee.Kind == "Var") { + assert(callee.Variable.Kind == "Func"); + var origName = callee.Variable.Name[0]; + var names = [ origName, otherDestructorName(origName) ]; + for (var name of names) { + if (name) + callees.push({'kind': 'direct', 'name': name}); + } + } else { + assert(callee.Kind == "Drf"); + if (callee.Exp[0].Kind == "Fld") { + var field = callee.Exp[0].Field; + var fieldName = field.Name[0]; + var csuName = field.FieldCSU.Type.Name; + var functions = null; + if ("FieldInstanceFunction" in field) + functions = findVirtualFunctions(csuName, fieldName); + if (functions) { + // Known set of virtual call targets. + for (var name of functions) + callees.push({'kind': "direct", 'name': name}); + } else { + // Unknown set of call targets. Non-virtual field call, + // or virtual call on an nsISupports object. + callees.push({'kind': "field", 'csu': csuName, 'field': fieldName}); + } + } else if (callee.Exp[0].Kind == "Var") { + // indirect call through a variable. + callees.push({'kind': "indirect", 'variable': callee.Exp[0].Variable.Name[0]}); + } else { + // unknown call target. + callees.push({'kind': "unknown"}); + } + } + + return callees; +} + +var lastline; +function printOnce(line) +{ + if (line != lastline) { + print(line); + lastline = line; + } +} + function processBody(caller, body) { if (!('PEdge' in body)) return; + + lastline = null; for (var edge of body.PEdge) { if (edge.Kind != "Call") continue; - var callee = edge.Exp[0]; var suppressText = ""; var seen = seenCallees; if (edge.Index[0] in body.suppressed) { @@ -122,47 +180,22 @@ function processBody(caller, body) seen = seenSuppressedCallees; } var prologue = suppressText + memo(caller) + " "; - if (callee.Kind == "Var") { - assert(callee.Variable.Kind == "Func"); - var name = callee.Variable.Name[0]; - if (!(name in seen)) { - print("D " + prologue + memo(name)); - seen[name] = true; - } - var otherName = otherDestructorName(name); - if (otherName && !(otherName in seen)) { - print("D " + prologue + memo(otherName)); - seen[otherName] = true; - } - } else { - assert(callee.Kind == "Drf"); - if (callee.Exp[0].Kind == "Fld") { - var field = callee.Exp[0].Field; - var fieldName = field.Name[0]; - var csuName = field.FieldCSU.Type.Name; - var functions = null; - if ("FieldInstanceFunction" in field) - functions = findVirtualFunctions(csuName, fieldName); - if (functions) { - // Known set of virtual call targets. - for (var name of functions) { - if (!(name in seen)) { - print("D " + prologue + memo(name)); - seen[name] = true; - } - } - } else { - // Unknown set of call targets. Non-virtual field call, - // or virtual call on an nsISupports object. - print("F " + prologue + "CLASS " + csuName + " FIELD " + fieldName); + for (var callee of getCallees(edge)) { + if (callee.kind == 'direct') { + if (!(callee.name in seen)) { + seen[name] = true; + printOnce("D " + prologue + memo(callee.name)); } - } else if (callee.Exp[0].Kind == "Var") { - // indirect call through a variable. - print("I " + prologue + - "VARIABLE " + callee.Exp[0].Variable.Name[0]); + } else if (callee.kind == 'field') { + var { csu, field } = callee; + printOnce("F " + prologue + "CLASS " + csu + " FIELD " + field); + } else if (callee.kind == 'indirect') { + printOnce("I " + prologue + "VARIABLE " + callee.variable); + } else if (callee.kind == 'unknown') { + printOnce("I " + prologue + "VARIABLE UNKNOWN"); } else { - // unknown call target. - print("I " + prologue + "VARIABLE UNKNOWN"); + printErr("invalid " + callee.kind + " callee"); + debugger; } } } diff --git a/js/src/devtools/rootAnalysis/suppressedPoints.js b/js/src/devtools/rootAnalysis/suppressedPoints.js index ddf749aeb1c..7c54283a110 100644 --- a/js/src/devtools/rootAnalysis/suppressedPoints.js +++ b/js/src/devtools/rootAnalysis/suppressedPoints.js @@ -4,11 +4,13 @@ var functionBodies; -function suppressAllPoints(id) +function findAllPoints(blockId) { - var body = null; + var points = []; + var body; + for (var xbody of functionBodies) { - if (sameBlockId(xbody.BlockId, id)) { + if (sameBlockId(xbody.BlockId, blockId)) { assert(!body); body = xbody; } @@ -18,10 +20,12 @@ function suppressAllPoints(id) if (!("PEdge" in body)) return; for (var edge of body.PEdge) { - body.suppressed[edge.Index[0]] = true; + points.push([body, edge.Index[0]]); if (edge.Kind == "Loop") - suppressAllPoints(edge.BlockId); + Array.prototype.push.apply(points, findAllPoints(edge.BlockId)); } + + return points; } function isMatchingDestructor(constructor, edge) @@ -46,20 +50,13 @@ function isMatchingDestructor(constructor, edge) return sameVariable(constructExp.Variable, destructExp.Variable); } -// Compute the points within a function body where GC is suppressed. -function computeSuppressedPoints(body) +function allRAIIGuardedCallPoints(body, isConstructor) { - var successors = []; - if (!("PEdge" in body)) - return; + return []; - for (var edge of body.PEdge) { - var source = edge.Index[0]; - if (!(source in successors)) - successors[source] = []; - successors[source].push(edge); - } + var points = []; + var successors = getSuccessors(body); for (var edge of body.PEdge) { if (edge.Kind != "Call") @@ -69,30 +66,20 @@ function computeSuppressedPoints(body) continue; var variable = callee.Variable; assert(variable.Kind == "Func"); - if (!isSuppressConstructor(variable.Name[0])) + if (!isConstructor(variable.Name[0])) continue; if (edge.PEdgeCallInstance.Exp.Kind != "Var") continue; - var seen = []; - var worklist = [edge.Index[1]]; - while (worklist.length) { - var point = worklist.pop(); - if (point in seen) - continue; - seen[point] = true; - body.suppressed[point] = true; - if (!(point in successors)) - continue; - for (var nedge of successors[point]) { - if (isMatchingDestructor(edge, nedge)) - continue; - if (nedge.Kind == "Loop") - suppressAllPoints(nedge.BlockId); - worklist.push(nedge.Index[1]); - } - } + Array.prototype.push.apply(points, pointsInRAIIScope(body, edge, successors)); } - return []; + return points; +} + +// Compute the points within a function body where GC is suppressed. +function computeSuppressedPoints(body) +{ + for (var [pbody, id] of allRAIIGuardedCallPoints(body, isSuppressConstructor)) + pbody.suppressed[id] = true; } diff --git a/js/src/devtools/rootAnalysis/utility.js b/js/src/devtools/rootAnalysis/utility.js index b74eb263d1e..9b7487355ee 100644 --- a/js/src/devtools/rootAnalysis/utility.js +++ b/js/src/devtools/rootAnalysis/utility.js @@ -13,6 +13,10 @@ function assert(x, msg) throw "assertion failed: " + (Error().stack); } +function defined(x) { + return x !== undefined; +} + function xprint(x, padding) { if (!padding) @@ -54,6 +58,51 @@ function sameVariable(var0, var1) return var0.Kind == var1.Kind; } +function blockIdentifier(body) +{ + if (body.BlockId.Kind == "Loop") + return body.BlockId.Loop; + assert(body.BlockId.Kind == "Function", "body.Kind should be Function, not " + body.BlockId.Kind); + return body.BlockId.Variable.Name[0]; +} + +function collectBodyEdges(body) +{ + body.predecessors = []; + body.successors = []; + if (!("PEdge" in body)) + return; + + for (var edge of body.PEdge) { + var [ source, target ] = edge.Index; + if (!(target in body.predecessors)) + body.predecessors[target] = []; + body.predecessors[target].push(edge); + if (!(source in body.successors)) + body.successors[source] = []; + body.successors[source].push(edge); + } +} + +function getPredecessors(body) +{ + try { + if (!('predecessors' in body)) + collectBodyEdges(body); + } catch (e) { + debugger; + printErr("body is " + body); + } + return body.predecessors; +} + +function getSuccessors(body) +{ + if (!('successors' in body)) + collectBodyEdges(body); + return body.successors; +} + function otherDestructorName(name) { // gcc's information for destructors can be pretty messed up. Some functions From bf6cca7cb09023a46a1ff2953b5893aa6491004c Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Fri, 23 Aug 2013 13:03:23 -0700 Subject: [PATCH 27/87] Bug 908825 - Assorted hazard analysis changes+fixes to get rooting analysis running on build slaves --HG-- extra : rebase_source : bff2e12a00934391ae50ce288d903d5bea6600c8 --- js/src/devtools/rootAnalysis/analyze.py | 82 ++++++++++---------- js/src/devtools/rootAnalysis/analyzeRoots.js | 2 +- js/src/devtools/rootAnalysis/build.b2g | 4 + js/src/devtools/rootAnalysis/build.browser | 4 + js/src/devtools/rootAnalysis/build.js | 11 +++ js/src/devtools/rootAnalysis/build.shell | 7 ++ js/src/devtools/rootAnalysis/run_complete | 9 ++- 7 files changed, 76 insertions(+), 43 deletions(-) create mode 100755 js/src/devtools/rootAnalysis/build.b2g create mode 100755 js/src/devtools/rootAnalysis/build.browser create mode 100755 js/src/devtools/rootAnalysis/build.js create mode 100755 js/src/devtools/rootAnalysis/build.shell diff --git a/js/src/devtools/rootAnalysis/analyze.py b/js/src/devtools/rootAnalysis/analyze.py index fbe88b694ee..0ed2aede89d 100755 --- a/js/src/devtools/rootAnalysis/analyze.py +++ b/js/src/devtools/rootAnalysis/analyze.py @@ -18,11 +18,10 @@ import re def env(config): e = dict(os.environ) - e['PATH'] = '%s:%s/bin' % (e['PATH'], config['sixgill']) - e['XDB'] = '%(sixgill)s/bin/xdb.so' % config - e['SOURCE_ROOT'] = config['source'] or e.get('TARGET', '') - e['TARGET_OBJ'] = config['objdir'] - e['TARGET'] = config['source'] + e['PATH'] = '%s:%s' % (e['PATH'], config['sixgill_bin']) + e['XDB'] = '%(sixgill_bin)s/xdb.so' % config + e['SOURCE'] = config['source'] + e['ANALYZED_OBJDIR'] = config['objdir'] return e def fill(command, config): @@ -96,11 +95,12 @@ def generate_hazards(config, outfilename): subprocess.call(command, stdout=output) JOBS = { 'dbs': - (('%(CWD)s/run_complete', + (('%(ANALYSIS_SCRIPTDIR)s/run_complete', '--foreground', '--build-root=%(objdir)s', - '--work=dir=work', - '-b', '%(sixgill)s/bin', + '--wrap-dir=%(sixgill)s/scripts/wrap_gcc', + '--work-dir=work', + '-b', '%(sixgill_bin)s', '--buildcommand=%(buildcommand)s', '.'), ()), @@ -119,7 +119,7 @@ JOBS = { 'dbs': 'gcTypes.txt'), 'allFunctions': - (('%(sixgill)s/bin/xdbkeys', 'src_body.xdb',), + (('%(sixgill_bin)s/xdbkeys', 'src_body.xdb',), 'allFunctions.txt'), 'hazards': @@ -170,21 +170,23 @@ def run_job(name, config): print("Error renaming %s -> %s" % (temp, final)) raise -config = { 'CWD': os.path.dirname(__file__) } +config = { 'ANALYSIS_SCRIPTDIR': os.path.dirname(__file__) } -defaults = [ '%s/defaults.py' % config['CWD'] ] +defaults = [ '%s/defaults.py' % config['ANALYSIS_SCRIPTDIR'], + '%s/defaults.py' % os.getcwd() ] for default in defaults: try: execfile(default, config) + print("Loaded %s" % default) except: pass data = config.copy() parser = argparse.ArgumentParser(description='Statically analyze build tree for rooting hazards.') -parser.add_argument('target', metavar='TARGET', type=str, nargs='?', - help='run starting from this target') +parser.add_argument('step', metavar='STEP', type=str, nargs='?', + help='run starting from this step') parser.add_argument('--source', metavar='SOURCE', type=str, nargs='?', help='source code to analyze') parser.add_argument('--upto', metavar='UPTO', type=str, nargs='?', @@ -192,14 +194,16 @@ parser.add_argument('--upto', metavar='UPTO', type=str, nargs='?', parser.add_argument('--jobs', '-j', default=4, metavar='JOBS', type=int, help='number of simultaneous analyzeRoots.js jobs') parser.add_argument('--list', const=True, nargs='?', type=bool, - help='display available targets') + help='display available steps') parser.add_argument('--buildcommand', '--build', '-b', type=str, nargs='?', help='command to build the tree being analyzed') parser.add_argument('--tag', '-t', type=str, nargs='?', help='name of job, also sets build command to "build."') args = parser.parse_args() -data.update(vars(args)) +for k,v in vars(args).items(): + if v is not None: + data[k] = v if args.tag and not args.buildcommand: args.buildcommand="build.%s" % args.tag @@ -211,46 +215,44 @@ elif 'BUILD' in os.environ: else: data['buildcommand'] = 'make -j4 -s' -if 'TARGET_OBJ' in os.environ: - data['objdir'] = os.environ['TARGET_OBJ'] +if 'ANALYZED_OBJDIR' in os.environ: + data['objdir'] = os.environ['ANALYZED_OBJDIR'] -if args.target: - data['source'] = args.target -elif 'TARGET' in os.environ: - data['source'] = os.environ['TARGET'] +if 'SOURCE' in os.environ: + data['source'] = os.environ['SOURCE'] -targets = [ 'dbs', - 'callgraph', - 'gcTypes', - 'gcFunctions', - 'allFunctions', - 'hazards' ] +steps = [ 'dbs', + 'callgraph', + 'gcTypes', + 'gcFunctions', + 'allFunctions', + 'hazards' ] if args.list: - for target in targets: - command, outfilename = JOBS[target] + for step in steps: + command, outfilename = JOBS[step] if outfilename: - print("%s -> %s" % (target, outfilename)) + print("%s -> %s" % (step, outfilename)) else: - print(target) + print(step) sys.exit(0) -for target in targets: - command, outfiles = JOBS[target] +for step in steps: + command, outfiles = JOBS[step] if isinstance(outfiles, basestring): - data[target] = outfiles + data[step] = outfiles else: outfile = 0 for (i, name) in out_indexes(command): data[name] = outfiles[outfile] outfile += 1 - assert len(outfiles) == outfile, 'target %s: mismatched number of output files and params' % target + assert len(outfiles) == outfile, 'step %s: mismatched number of output files and params' % step -if args.target: - targets = targets[targets.index(args.target):] +if args.step: + steps = steps[steps.index(args.step):] if args.upto: - targets = targets[:targets.index(args.upto)+1] + steps = steps[:steps.index(args.upto)+1] -for target in targets: - run_job(target, data) +for step in steps: + run_job(step, data) diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index 9a265bd7983..168f90cb771 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -6,7 +6,7 @@ loadRelativeToScript('utility.js'); loadRelativeToScript('annotations.js'); loadRelativeToScript('suppressedPoints.js'); -var sourceRoot = (environment['SOURCE_ROOT'] || '') + '/' +var sourceRoot = (environment['SOURCE'] || '') + '/' var functionBodies; diff --git a/js/src/devtools/rootAnalysis/build.b2g b/js/src/devtools/rootAnalysis/build.b2g new file mode 100755 index 00000000000..902988d2496 --- /dev/null +++ b/js/src/devtools/rootAnalysis/build.b2g @@ -0,0 +1,4 @@ +#!/bin/sh + +cd $SOURCE +exec env MOZCONFIG=$SOURCE/mozconfig-b2g-ra ./mach build diff --git a/js/src/devtools/rootAnalysis/build.browser b/js/src/devtools/rootAnalysis/build.browser new file mode 100755 index 00000000000..da360bb68a6 --- /dev/null +++ b/js/src/devtools/rootAnalysis/build.browser @@ -0,0 +1,4 @@ +#!/bin/sh + +cd $SOURCE +exec ./mach build diff --git a/js/src/devtools/rootAnalysis/build.js b/js/src/devtools/rootAnalysis/build.js new file mode 100755 index 00000000000..d934c5663d4 --- /dev/null +++ b/js/src/devtools/rootAnalysis/build.js @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +cd $SOURCE +make -f client.mk configure +make -C $ANALYZED_OBJDIR export +./mach build -X nsprpub mfbt memory memory/mozalloc modules/zlib mozglue js/src xpcom/glue js/ductwork/debugger js/ipc js/xpconnect/loader js/xpconnect/wrappers js/xpconnect/src +status=$? +echo "[[[[ build.js complete, exit code $status ]]]]" +exit $status diff --git a/js/src/devtools/rootAnalysis/build.shell b/js/src/devtools/rootAnalysis/build.shell new file mode 100755 index 00000000000..46360bc0caa --- /dev/null +++ b/js/src/devtools/rootAnalysis/build.shell @@ -0,0 +1,7 @@ +#!/bin/sh -x + +mkdir $ANALYZED_OBJDIR +cd $ANALYZED_OBJDIR +$SOURCE/js/src/configure --enable-debug --enable-optimize --enable-root-analysis +# perl -i -pe 's!ccache ([gc])!$1!' "$TARGET_BUILDROOT/config/autoconf.mk" +make -j12 -s diff --git a/js/src/devtools/rootAnalysis/run_complete b/js/src/devtools/rootAnalysis/run_complete index 58d8bd431b9..5cbff97793c 100755 --- a/js/src/devtools/rootAnalysis/run_complete +++ b/js/src/devtools/rootAnalysis/run_complete @@ -75,6 +75,7 @@ if ($old_dir ne "" && not -d $old_dir) { } $WORKDIR ||= "sixgill-work"; +mkdir($WORKDIR, 0755) if ! -d $WORKDIR; $poll_file ||= "$WORKDIR/poll.file"; $build_dir ||= "$WORKDIR/js-inbound-xgill"; @@ -212,14 +213,18 @@ sub run_build my $address = get_manager_address($log_file); # write the configuration file for the wrapper script. - open(CONFIG, "> $wrap_dir/xgill.config"); + my $config_file = "$WORKDIR/xgill.config"; + open(CONFIG, ">", $config_file) or die "create $config_file: $!"; print CONFIG "$prefix_dir\n"; - print CONFIG "$result_dir/build_xgill.log\n"; + print CONFIG Cwd::abs_path("$result_dir/build_xgill.log")."\n"; print CONFIG "$address\n"; print CONFIG "-fplugin-arg-xgill-annfile=$ann_file\n" if ($ann_file ne "" && -e $ann_file); close(CONFIG); + # Tell the wrapper where to find the config + $ENV{"XGILL_CONFIG"} = Cwd::abs_path($config_file); + # update the PATH so that the build will see the wrappers. $ENV{"PATH"} = "$wrap_dir:" . $ENV{"PATH"}; From dd9100559d39671f44c504f2e53fd5411af36f86 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Fri, 23 Aug 2013 15:53:46 -0700 Subject: [PATCH 28/87] Bug 908891 - Fix remaining exact rooting hazards in js/ipc; r=evilpie --HG-- extra : rebase_source : d48dfa50ed83c8c3d3c344467c6bd0b702a3263a --- js/ipc/JavaScriptParent.cpp | 19 ++++++++++--------- js/ipc/JavaScriptShared.cpp | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/js/ipc/JavaScriptParent.cpp b/js/ipc/JavaScriptParent.cpp index b5ce31d91a2..8db76a12270 100644 --- a/js/ipc/JavaScriptParent.cpp +++ b/js/ipc/JavaScriptParent.cpp @@ -395,7 +395,7 @@ JavaScriptParent::call(JSContext *cx, HandleObject proxy, const CallArgs &args) for (size_t i = 0; i < args.length() + 2; i++) { v = args.base()[i]; if (v.isObject()) { - JSObject *obj = &v.toObject(); + RootedObject obj(cx, &v.toObject()); if (xpc::IsOutObject(cx, obj)) { // Make sure it is not an in-out object. bool found; @@ -554,8 +554,9 @@ JavaScriptParent::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t f JSObject * JavaScriptParent::unwrap(JSContext *cx, ObjectId objId) { - if (JSObject *obj = findObject(objId)) { - if (!JS_WrapObject(cx, &obj)) + RootedObject obj(cx, findObject(objId)); + if (obj) { + if (!JS_WrapObject(cx, obj.address())) return NULL; return obj; } @@ -570,12 +571,12 @@ JavaScriptParent::unwrap(JSContext *cx, ObjectId objId) RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); RootedValue v(cx, UndefinedValue()); - JSObject *obj = NewProxyObject(cx, - &CPOWProxyHandler::singleton, - v, - NULL, - global, - callable ? ProxyIsCallable : ProxyNotCallable); + obj = NewProxyObject(cx, + &CPOWProxyHandler::singleton, + v, + NULL, + global, + callable ? ProxyIsCallable : ProxyNotCallable); if (!obj) return NULL; diff --git a/js/ipc/JavaScriptShared.cpp b/js/ipc/JavaScriptShared.cpp index b986c5dd243..de8e0335786 100644 --- a/js/ipc/JavaScriptShared.cpp +++ b/js/ipc/JavaScriptShared.cpp @@ -168,7 +168,7 @@ JavaScriptShared::toVariant(JSContext *cx, jsval from, JSVariant *to) case JSTYPE_OBJECT: case JSTYPE_FUNCTION: { - JSObject *obj = from.toObjectOrNull(); + RootedObject obj(cx, from.toObjectOrNull()); if (!obj) { JS_ASSERT(from == JSVAL_NULL); *to = uint64_t(0); From 87431f5fbec66a747fe5825c720c957cf71d8d49 Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Fri, 23 Aug 2013 19:04:19 -0400 Subject: [PATCH 29/87] Bug 908692 - Electrolysis: Geolocation permission box doesn't open either. r=felipe --- browser/components/nsBrowserGlue.js | 42 ++++++++++++----------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 2d4628dc24c..fca44ef7b19 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -1733,16 +1733,21 @@ ContentPermissionPrompt.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]), - _getChromeWindow: function CPP_getChromeWindow(aWindow) { - var chromeWin = aWindow - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow) - .QueryInterface(Ci.nsIDOMChromeWindow); - return chromeWin; + _getBrowserForRequest: function (aRequest) { + var browser; + try { + // "element" is only defined in e10s mode, otherwise it throws. + browser = aRequest.element; + } catch (e) {} + if (!browser) { + var requestingWindow = aRequest.window.top; + // find the requesting browser or iframe + browser = requestingWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell) + .chromeEventHandler; + } + return browser; }, /** @@ -1767,19 +1772,7 @@ ContentPermissionPrompt.prototype = { var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); - var browser; - try { - // "element" is only defined in e10s mode, otherwise it throws. - browser = aRequest.element; - } catch (e) {} - if (!browser) { - var requestingWindow = aRequest.window.top; - // find the requesting browser or iframe - browser = requestingWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler; - } + var browser = this._getBrowserForRequest(aRequest); var chromeWin = browser.ownerDocument.defaultView; var requestPrincipal = aRequest.principal; @@ -1896,8 +1889,7 @@ ContentPermissionPrompt.prototype = { }); } - var requestingWindow = aRequest.window.top; - var chromeWin = this._getChromeWindow(requestingWindow).wrappedJSObject; + var chromeWin = this._getBrowserForRequest(aRequest).ownerDocument.defaultView; var link = chromeWin.document.getElementById("geolocation-learnmore-link"); link.value = browserBundle.GetStringFromName("geolocation.learnMore"); link.href = Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL"); From 0976f7fb146bdd82bb5ff35e1f763ce1917720d9 Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Fri, 23 Aug 2013 19:04:20 -0400 Subject: [PATCH 30/87] Bug 908213 - Fix CPOWs test failure and make it more robust. r=dvander --- content/base/test/chrome/cpows_child.js | 5 ++++- content/base/test/chrome/cpows_parent.xul | 5 +++++ content/base/test/chrome/test_cpows.xul | 5 ++++- dom/ipc/TabChild.cpp | 4 ++-- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/content/base/test/chrome/cpows_child.js b/content/base/test/chrome/cpows_child.js index a53c7c1940d..d8a27bbfb6a 100644 --- a/content/base/test/chrome/cpows_child.js +++ b/content/base/test/chrome/cpows_child.js @@ -5,7 +5,10 @@ content.document.title = "Hello, Kitty"; (function start() { sync_test(); async_test(); - sendAsyncMessage("cpows:done", {}); + // The sync-ness of this call is important, because otherwise + // we tear down the child's document while we are + // still in the async test in the parent. + sendSyncMessage("cpows:done", {}); } )(); diff --git a/content/base/test/chrome/cpows_parent.xul b/content/base/test/chrome/cpows_parent.xul index 7d9592a8f96..e98b08b29e0 100644 --- a/content/base/test/chrome/cpows_parent.xul +++ b/content/base/test/chrome/cpows_parent.xul @@ -17,6 +17,11 @@ return opener.wrappedJSObject.ok(condition, message); } + // Make sure that an error in this file actually causes the test to fail. + window.onerror = function (msg, url, line) { + ok(false, "Error while executing: \n" + msg + "\n" + url + ":" + line); + }; + function testCpowMessage(message) { ok(message.json.check == "ok", "correct json"); diff --git a/content/base/test/chrome/test_cpows.xul b/content/base/test/chrome/test_cpows.xul index 0f10f509439..f47f0c57534 100644 --- a/content/base/test/chrome/test_cpows.xul +++ b/content/base/test/chrome/test_cpows.xul @@ -21,7 +21,10 @@ } addLoadEvent(function() { - window.open("cpows_parent.xul", "", "chrome"); + // We don't want to set browser.tabs.remote to true, but still have CPOWs enabled. + SpecialPowers.pushPrefEnv({"set": [["dom.ipc.cpows.force-enabled", true]]}, function() { + window.open("cpows_parent.xul", "", "chrome"); + }); }); ]]> diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 45fdecf7ee4..7cd75f93683 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -2339,8 +2339,8 @@ TabChild::InitRenderingState() // This state can't really change during the lifetime of the child. sCpowsEnabled = Preferences::GetBool("browser.tabs.remote", false); - if (Preferences::GetBool("dom.ipc.cpows.force-disabled", false)) - sCpowsEnabled = false; + if (Preferences::GetBool("dom.ipc.cpows.force-enabled", false)) + sCpowsEnabled = true; return true; } From 7b2f7d897c406700f3a640b691bb26f75ba701ef Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang Date: Fri, 23 Aug 2013 16:19:36 -0700 Subject: [PATCH 31/87] Bug 880543: Update NSS to NSS_3_15_2_BETA1, mainly to pick up AES-GCM TLS cipher suites. --- security/nss/TAG-INFO | 2 +- security/nss/coreconf/coreconf.dep | 1 + security/nss/doc/certutil.xml | 23 +- security/nss/doc/cmsutil.xml | 39 +- security/nss/doc/crlutil.xml | 14 + security/nss/doc/html/certutil.html | 178 +++--- security/nss/doc/html/cmsutil.html | 14 +- security/nss/doc/html/crlutil.html | 14 +- security/nss/doc/html/modutil.html | 8 +- security/nss/doc/html/pk12util.html | 10 +- security/nss/doc/html/pp.html | 10 +- security/nss/doc/html/signtool.html | 8 +- security/nss/doc/html/signver.html | 12 +- security/nss/doc/html/ssltap.html | 8 +- security/nss/doc/html/vfychain.html | 8 +- security/nss/doc/html/vfyserv.html | 8 +- security/nss/doc/nroff/certutil.1 | 268 ++++---- security/nss/doc/nroff/cmsutil.1 | 37 +- security/nss/doc/nroff/crlutil.1 | 20 +- security/nss/doc/nroff/pk12util.1 | 10 +- security/nss/doc/nroff/pp.1 | 12 +- security/nss/doc/nroff/signtool.1 | 10 +- security/nss/doc/nroff/signver.1 | 10 +- security/nss/doc/nroff/ssltap.1 | 10 +- security/nss/doc/nroff/vfychain.1 | 10 +- security/nss/doc/nroff/vfyserv.1 | 10 +- security/nss/lib/certhigh/ocsp.c | 29 +- security/nss/lib/cryptohi/cryptohi.h | 4 +- security/nss/lib/freebl/mpi/README | 4 - security/nss/lib/nss/nss.h | 6 +- security/nss/lib/pk11wrap/pk11pub.h | 1 + security/nss/lib/pkcs12/p12d.c | 1 + security/nss/lib/softoken/pkcs11c.c | 2 + security/nss/lib/softoken/softkver.h | 6 +- security/nss/lib/ssl/ssl.h | 12 +- security/nss/lib/ssl/ssl3con.c | 894 +++++++++++++++++---------- security/nss/lib/ssl/ssl3ecc.c | 4 + security/nss/lib/ssl/ssl3ext.c | 2 +- security/nss/lib/ssl/sslcon.c | 1 - security/nss/lib/ssl/sslenum.c | 8 + security/nss/lib/ssl/sslimpl.h | 55 +- security/nss/lib/ssl/sslinfo.c | 11 +- security/nss/lib/ssl/sslproto.h | 9 + security/nss/lib/ssl/sslsock.c | 90 +-- security/nss/lib/ssl/sslt.h | 11 +- security/nss/lib/util/nssutil.h | 6 +- security/nss/lib/util/utilpars.c | 14 +- security/nss/tests/ssl/ssl.sh | 4 +- security/nss/tests/ssl/sslcov.txt | 3 + security/nss/tests/ssl/sslstress.txt | 2 + 50 files changed, 1115 insertions(+), 818 deletions(-) diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index 6b09212ac76..225d6d53382 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_15_1_RTM +NSS_3_15_2_BETA1 diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 5182f75552c..590d1bfaeee 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,3 +10,4 @@ */ #error "Do not include this header file." + diff --git a/security/nss/doc/certutil.xml b/security/nss/doc/certutil.xml index 010ef31aa2f..11b5837bca7 100644 --- a/security/nss/doc/certutil.xml +++ b/security/nss/doc/certutil.xml @@ -638,6 +638,27 @@ of the attribute codes: Add the Subject Key ID extension to the certificate. X.509 certificate extensions are described in RFC 5280. + + --extNC + Add a Name Constraint extension to the certificate. X.509 certificate extensions are described in RFC 5280. + + + + --keyAttrFlags attrflags + +PKCS #11 key Attributes. Comma separated list of key attribute flags, selected from the following list of choices: {token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable} + + + + --keyFlagsOn opflags + --keyFlagsOff opflags + +PKCS #11 key Operation Flags. +Comma separated list of one or more of the following: +{token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable} + + + --source-dir certdir Identify the certificate database directory to upgrade. @@ -800,7 +821,7 @@ XKYFwPMJjWCihVku6bw/ihZfuMHhxK22Nue6inNQ6eDu7WmrqL8z3iUrQwxs+WiF ob2rb8XRVVJkzXdXxlk4uo3UtNvw8sAz7sWD71qxKaIHU5q49zijfg== -----END CERTIFICATE----- -For a humam-readable display +For a human-readable display $ certutil -L -d sql:$HOME/nssdb -n my-ca-cert Certificate: Data: diff --git a/security/nss/doc/cmsutil.xml b/security/nss/doc/cmsutil.xml index c4179627774..ba45b99fdb7 100644 --- a/security/nss/doc/cmsutil.xml +++ b/security/nss/doc/cmsutil.xml @@ -89,8 +89,15 @@ The options and arguments for the cmsutil command are defined as follows: Arguments - Option arguments modify an action and are lowercase. + Option arguments modify an action. + + -b + + Decode a batch of files named in infile. + + + -c content @@ -112,13 +119,27 @@ The options and arguments for the cmsutil command are defined as follows: + + -f pwfile + + Use password file to set password on all PKCS#11 tokens. + + + -G Include a signing time attribute (sign only). - + + + -H hash + + Use specified hash algorithm (default:SHA1). + + + -h num @@ -133,6 +154,13 @@ The options and arguments for the cmsutil command are defined as follows: + + -k + + Keep decoded encryption certs in permanent cert db. + + + -N nickname @@ -192,6 +220,13 @@ For certificates-only message, list of certificates to send. + + -v + + Print debugging information. + + + -Y ekprefnick diff --git a/security/nss/doc/crlutil.xml b/security/nss/doc/crlutil.xml index 2b1eac20518..a6dddd4d615 100644 --- a/security/nss/doc/crlutil.xml +++ b/security/nss/doc/crlutil.xml @@ -266,6 +266,20 @@ Specify the url. + + -w pwd-string + + Provide db password in command line. + + + + + -Z algorithm + + Specify the hash algorithm to use for signing the CRL. + + + diff --git a/security/nss/doc/html/certutil.html b/security/nss/doc/html/certutil.html index ddfb0989073..5639d653453 100644 --- a/security/nss/doc/html/certutil.html +++ b/security/nss/doc/html/certutil.html @@ -1,31 +1,24 @@ -CERTUTIL

Name

certutil — Manage keys and certificate in the the NSS database.

Synopsis

certutil [options] [[arguments]]

STATUS

This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 -

Description

The Certificate Database Tool, certutil, is a command-line utility that manages certs and keys in both NSS databases and other NSS tokens (such as smart cards). It can specifically list, generate, modify, or delete certificates within the database, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database.

The key and certificate management process generally includes certificate issuance once keys and certificates have been created in the key database. This document discusses certificate and key database management. For information security module database management, see the modutil manpage.

Options and Arguments

Running certutil always requires one and only one option to specify the type of certificate operation. Each option may take arguments, anywhere from none to multiple arguments. Run the command option and -H to see the arguments available for each command option.

Command Options

Command options are typically upper case.

-A

Add an existing certificate to a certificate database. The certificate database should already exist; if one is not present, this command option will initialize one by default.

-B

Run a series of commands from the specified batch file. This requires the -i argument.

-C

Create a new binary certificate file from a binary certificate request file. Use the -i argument to specify the certificate request file. If this argument is not used, certutil prompts for a filename.

-D

Delete a certificate from the certificate database.

-E

Add an email certificate to the certificate database.

-F

Delete a private key from a key database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the +CERTUTIL

Name

certutil — Manage keys and certificate in both NSS databases and other NSS tokens

Synopsis

certutil [options] [[arguments]]

STATUS

This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +

Description

The Certificate Database Tool, certutil, is a command-line utility that can create and modify certificate and key databases. It can specifically list, generate, modify, or delete certificates, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database.

Certificate issuance, part of the key and certificate management process, requires that keys and certificates be created in the key database. This document discusses certificate and key database management. For information on the security module database management, see the modutil manpage.

Command Options and Arguments

Running certutil always requires one and only one command option to specify the type of certificate operation. Each command option may take zero or more arguments. The command option -H will list all the command options and their relevant arguments.

Command Options

-A

Add an existing certificate to a certificate database. The certificate database should already exist; if one is not present, this command option will initialize one by default.

-B

Run a series of commands from the specified batch file. This requires the -i argument.

-C

Create a new binary certificate file from a binary certificate request file. Use the -i argument to specify the certificate request file. If this argument is not used, certutil prompts for a filename.

-D

Delete a certificate from the certificate database.

-E

Add an email certificate to the certificate database.

-F

Delete a private key from a key database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the -d argument. Use the -k argument to specify explicitly whether to delete a DSA, RSA, or ECC key. If you don't use the -k argument, the option looks for an RSA key matching the specified nickname.

-When you delete keys, be sure to also remove any certificates associated with those keys from the certificate database, by using -D. Some smart cards do not let you remove a public key you have generated. In such a case, only the private key is deleted from the key pair. You can display the public key with the command certutil -K -h tokenname.

-G

Generate a new public and private key pair within a key database. The key database should already exist; if one is not present, this option will initialize one by default. Some smart cards can store only one key pair. If you create a new key pair for such a card, the previous pair is overwritten.

-H

Display a list of the command options and arguments used by the Certificate Database Tool.

-K

List the key ID of keys in the key database. A key ID is the modulus of the RSA key or the publicValue of the DSA key. IDs are displayed in hexadecimal ("0x" is not shown).

-L

List all the certificates, or display information about a named certificate, in a certificate database. -Use the -h tokenname argument to specify the certificate database on a particular hardware or software token.

-M

Modify a certificate's trust attributes using the values of the -t argument.

-N

Create new certificate and key databases.

-O

Print the certificate chain.

-R

Create a certificate request file that can be submitted to a Certificate Authority (CA) for processing into a finished certificate. Output defaults to standard out unless you use -o output-file argument. +When you delete keys, be sure to also remove any certificates associated with those keys from the certificate database, by using -D. Some smart cards do not let you remove a public key you have generated. In such a case, only the private key is deleted from the key pair. You can display the public key with the command certutil -K -h tokenname.

-G

Generate a new public and private key pair within a key database. The key database should already exist; if one is not present, this command option will initialize one by default. Some smart cards can store only one key pair. If you create a new key pair for such a card, the previous pair is overwritten.

-H

Display a list of the command options and arguments.

-K

List the key ID of keys in the key database. A key ID is the modulus of the RSA key or the publicValue of the DSA key. IDs are displayed in hexadecimal ("0x" is not shown).

-L

List all the certificates, or display information about a named certificate, in a certificate database. +Use the -h tokenname argument to specify the certificate database on a particular hardware or software token.

-M

Modify a certificate's trust attributes using the values of the -t argument.

-N

Create new certificate and key databases.

-O

Print the certificate chain.

-R

Create a certificate request file that can be submitted to a Certificate Authority (CA) for processing into a finished certificate. Output defaults to standard out unless you use -o output-file argument. -Use the -a argument to specify ASCII output.

-S

Create an individual certificate and add it to a certificate database.

-T

Reset the key database or token.

-U

List all available modules or print a single named module.

-V

Check the validity of a certificate and its attributes.

-W

Change the password to a key database.

--merge

Merge a source database into the target database. This is used to merge legacy NSS databases (cert8.db and key3.db) into the newer SQLite databases (cert9.db and key4.db).

--upgrade-merge

Upgrade an old database and merge it into a new database. This is used to migrate legacy NSS databases (cert8.db and key3.db) into the newer SQLite databases (cert9.db and key4.db).

Arguments

Arguments modify a command option and are usually lower case, numbers, or symbols.

-a

Use ASCII format or allow the use of ASCII format for input or output. This formatting follows RFC 1113. +Use the -a argument to specify ASCII output.

-S

Create an individual certificate and add it to a certificate database.

-T

Reset the key database or token.

-U

List all available modules or print a single named module.

-V

Check the validity of a certificate and its attributes.

-W

Change the password to a key database.

--merge

Merge two databases into one.

--upgrade-merge

Upgrade an old database and merge it into a new database. This is used to migrate legacy NSS databases (cert8.db and key3.db) into the newer SQLite databases (cert9.db and key4.db).

Arguments

Arguments modify a command option and are usually lower case, numbers, or symbols.

-a

Use ASCII format or allow the use of ASCII format for input or output. This formatting follows RFC 1113. For certificate requests, ASCII output defaults to standard output unless redirected.

-b validity-time

Specify a time at which a certificate is required to be valid. Use when checking certificate validity with the -V option. The format of the validity-time argument is YYMMDDHHMMSS[+HHMM|-HHMM|Z], which allows offsets to be set relative to the validity end time. Specifying seconds (SS) is optional. When specifying an explicit time, use a Z at the end of the term, YYMMDDHHMMSSZ, to close it. When specifying an offset time, use YYMMDDHHMMSS+HHMM or YYMMDDHHMMSS-HHMM for adding or subtracting time, respectively.

If this option is not used, the validity check defaults to the current system time.

-c issuer

Identify the certificate of the CA from which a new certificate will derive its authenticity. Use the exact nickname or alias of the CA certificate, or use the CA's email address. Bracket the issuer string - with quotation marks if it contains spaces.

-d [prefix]directory

Specify the database directory containing the certificate and key database files.

certutil supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

NSS recognizes the following prefixes:

  • sql: explicitly requests the newer database

  • dbm: explicitly requests the older database

  • extern: explicitly reserved for future use

-e

Check a certificate's signature during the process of validating a certificate.

-f password-file

Specify a file that will automatically supply the password to include in a certificate + with quotation marks if it contains spaces.

-d [prefix]directory

Specify the database directory containing the certificate and key database files.

certutil supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt).

NSS recognizes the following prefixes:

  • sql: requests the newer database

  • dbm: requests the legacy database

If no prefix is specified the default type is retrieved from NSS_DEFAULT_DB_TYPE. If NSS_DEFAULT_DB_TYPE is not set then dbm: is the default.

-e

Check a certificate's signature during the process of validating a certificate.

-f password-file

Specify a file that will automatically supply the password to include in a certificate or to access a certificate database. This is a plain-text file containing one password. Be sure to prevent - unauthorized access to this file.

-g keysize

Set a key size to use when generating new public and private key pairs. The minimum is 512 bits and the maximum is 8192 bits. The default is 1024 bits. Any size between the minimum and maximum is allowed.

-h tokenname

Specify the name of a token to use or act on. Unless specified otherwise the default token is an internal slot.

-i input_file

Pass an input file to the command. Depending on the command option, an input file can be a specific certificate, a certificate request file, or a batch file of commands.

-k rsa|dsa|ec|all

Specify the type of a key. The valid options are RSA, DSA, ECC, or all. The default value is rsa. Specifying the type of key can avoid mistakes caused by duplicate nicknames.

-k key-type-or-id

Specify the type or specific ID of a key.

- The valid key type options are RSA, DSA, ECC, or all. The default + unauthorized access to this file.

-g keysize

Set a key size to use when generating new public and private key pairs. The minimum is 512 bits and the maximum is 8192 bits. The default is 1024 bits. Any size between the minimum and maximum is allowed.

-h tokenname

Specify the name of a token to use or act on. If not specified the default token is the internal database slot.

-i input_file

Pass an input file to the command. Depending on the command option, an input file can be a specific certificate, a certificate request file, or a batch file of commands.

-k key-type-or-id

Specify the type or specific ID of a key.

+ The valid key type options are rsa, dsa, ec, or all. The default value is rsa. Specifying the type of key can avoid mistakes caused by duplicate nicknames. Giving a key type generates a new key pair; giving the ID of an existing key reuses that key pair (which is required to renew certificates). -

- The valid key type options are RSA, DSA, ECC, or all. The default - value is rsa. Specifying the type of key can avoid mistakes caused by - duplicate nicknames. Giving a key type generates a new key pair; - giving the ID of an existing key reuses that key pair (which is - required to renew certificates). -

-l

Display detailed information when validating a certificate with the -V option.

-m serial-number

Assign a unique serial number to a certificate being created. This operation should be performed by a CA. If no serial number is - provided a default serial number is made from the current time. Serial numbers are limited to integers

-n nickname

Specify the nickname of a certificate or key to list, create, add to a database, modify, or validate. Bracket the nickname string with quotation marks if it contains spaces.

-o output-file

Specify the output file name for new certificates or binary certificate requests. Bracket the output-file string with quotation marks if it contains spaces. If this argument is not used the output destination defaults to standard output.

-P dbPrefix

Specify the prefix used on the certificate and key database file. This argument is provided to support legacy servers. Most applications do not use a database prefix.

-p phone

Specify a contact telephone number to include in new certificates or certificate requests. Bracket this string with quotation marks if it contains spaces.

-q pqgfile or curve-name

Read an alternate PQG value from the specified file when generating DSA key pairs. If this argument is not used, certutil generates its own PQG value. PQG files are created with a separate DSA utility.

Elliptic curve name is one of the ones from SUITE B: nistp256, nistp384, nistp521

+

-l

Display detailed information when validating a certificate with the -V option.

-m serial-number

Assign a unique serial number to a certificate being created. This operation should be performed by a CA. If no serial number is provided a default serial number is made from the current time. Serial numbers are limited to integers

-n nickname

Specify the nickname of a certificate or key to list, create, add to a database, modify, or validate. Bracket the nickname string with quotation marks if it contains spaces.

-o output-file

Specify the output file name for new certificates or binary certificate requests. Bracket the output-file string with quotation marks if it contains spaces. If this argument is not used the output destination defaults to standard output.

-P dbPrefix

Specify the prefix used on the certificate and key database file. This argument is provided to support legacy servers. Most applications do not use a database prefix.

-p phone

Specify a contact telephone number to include in new certificates or certificate requests. Bracket this string with quotation marks if it contains spaces.

-q pqgfile or curve-name

Read an alternate PQG value from the specified file when generating DSA key pairs. If this argument is not used, certutil generates its own PQG value. PQG files are created with a separate DSA utility.

Elliptic curve name is one of the ones from SUITE B: nistp256, nistp384, nistp521

If NSS has been compiled with support curves outside of SUITE B: sect163k1, nistk163, sect163r1, sect163r2, nistb163, sect193r1, sect193r2, sect233k1, nistk233, @@ -55,7 +48,7 @@ of the attribute codes:

  • T - Trusted CA (implies c)

  • - C - rusted CA for client authentication (ssl server only) + C - trusted CA for client authentication (ssl server only)

  • u - user

  • @@ -116,7 +109,12 @@ of the attribute codes: msTrustListSign

  • critical -

  • X.509 certificate extensions are described in RFC 5280.

    -7 emailAddrs

    Add a comma-separated list of email addresses to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    -8 dns-names

    Add a comma-separated list of DNS names to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    --extAIA

    Add the Authority Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSIA

    Add the Subject Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extCP

    Add the Certificate Policies extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPM

    Add the Policy Mappings extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPC

    Add the Policy Constraints extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extIA

    Add the Inhibit Any Policy Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSKID

    Add the Subject Key ID extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --source-dir certdir

    Identify the certificate database directory to upgrade.

    --source-prefix certdir

    Give the prefix of the certificate and key databases to upgrade.

    --upgrade-id uniqueID

    Give the unique ID of the database to upgrade.

    --upgrade-token-name name

    Set the name of the token to use while it is being upgraded.

    -@ pwfile

    Give the name of a password file to use for the database being upgraded.

    Usage and Examples

    +

    X.509 certificate extensions are described in RFC 5280.

    -7 emailAddrs

    Add a comma-separated list of email addresses to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    -8 dns-names

    Add a comma-separated list of DNS names to the subject alternative name extension of a certificate or certificate request that is being created or added to the database. Subject alternative name extensions are described in Section 4.2.1.7 of RFC 3280.

    --extAIA

    Add the Authority Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSIA

    Add the Subject Information Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extCP

    Add the Certificate Policies extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPM

    Add the Policy Mappings extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extPC

    Add the Policy Constraints extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extIA

    Add the Inhibit Any Policy Access extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extSKID

    Add the Subject Key ID extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --extNC

    Add a Name Constraint extension to the certificate. X.509 certificate extensions are described in RFC 5280.

    --keyAttrFlags attrflags

    +PKCS #11 key Attributes. Comma separated list of key attribute flags, selected from the following list of choices: {token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable}

    --keyFlagsOn opflags, --keyFlagsOff opflags

    +PKCS #11 key Operation Flags. +Comma separated list of one or more of the following: +{token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable} +

    --source-dir certdir

    Identify the certificate database directory to upgrade.

    --source-prefix certdir

    Give the prefix of the certificate and key databases to upgrade.

    --upgrade-id uniqueID

    Give the unique ID of the database to upgrade.

    --upgrade-token-name name

    Set the name of the token to use while it is being upgraded.

    -@ pwfile

    Give the name of a password file to use for the database being upgraded.

    Usage and Examples

    Most of the command options in the examples listed here have more arguments available. The arguments included in these examples are the most common ones or are used to illustrate a specific scenario. Use the -H option to show the complete list of arguments for each command option.

    Creating New Security Databases

    Certificates, keys, and security modules related to managing certificates are stored in three related databases: @@ -144,44 +142,25 @@ of the attribute codes: The new certificate request can be output in ASCII format (-a) or can be written to a specified file (-o).

    For example: -

    $ certutil -R -k ec -q nistb409 -g 512 -s "CN=John Smith,O=Example Corp,L=Mountain View,ST=California,C=US" -d sql:/home/my/sharednssdb -p 650-555-0123 -a -o cert.cer
    +	

    $ certutil -R -k rsa -g 1024 -s "CN=John Smith,O=Example Corp,L=Mountain View,ST=California,C=US" -d sql:$HOME/nssdb -p 650-555-0123 -a -o cert.cer
     
     Generating key.  This may take a few moments...
     
    -
    -Certificate request generated by Netscape 
    -Phone: 650-555-0123
    -Common Name: John Smith
    -Email: (not ed)
    -Organization: Example Corp
    -State: California
    -Country: US
    -
    ------BEGIN NEW CERTIFICATE REQUEST-----
    -MIIBIDCBywIBADBmMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW
    -MBQGA1UEBxMNTW91bnRhaW4gVmlldzEVMBMGA1UEChMMRXhhbXBsZSBDb3JwMRMw
    -EQYDVQQDEwpKb2huIFNtaXRoMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMVUpDOZ
    -KmHnOx7reP8Cc0Lk+fFWEuYIDX9W5K/BioQOKvEjXyQZhit9aThzBVMoSf1Y1S8J
    -CzdUbCg1+IbnXaECAwEAAaAAMA0GCSqGSIb3DQEBBQUAA0EAryqZvpYrUtQ486Ny
    -qmtyQNjIi1F8c1Z+TL4uFYlMg8z6LG/J/u1E5t1QqB5e9Q4+BhRbrQjRR1JZx3tB
    -1hP9Gg==
    ------END NEW CERTIFICATE REQUEST-----

    Creating a Certificate

    +

    Creating a Certificate

    A valid certificate must be issued by a trusted CA. This can be done by specifying a CA certificate (-c) that is stored in the certificate database. If a CA key pair is not available, you can create a self-signed certificate using the -x argument with the -S command option.

    $ certutil -S -k rsa|dsa|ec -n certname -s subject [-c issuer |-x] -t trustargs -d [sql:]directory [-m serial-number] [-v valid-months] [-w offset-months] [-p phone] [-1] [-2] [-3] [-4] [-5 keyword] [-6 keyword] [-7 emailAddress] [-8 dns-names] [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA] [--extSKID]

    - The series of numbers and --ext* options set certificate extensions that can be added to the certificate when it is generated by the CA. + The series of numbers and --ext* options set certificate extensions that can be added to the certificate when it is generated by the CA. Interactive prompts will result.

    For example, this creates a self-signed certificate:

    $ certutil -S -s "CN=Example CA" -n my-ca-cert -x -t "C,C,C" -1 -2 -5 -m 3650

    +The interative prompts for key usage and whether any extensions are critical and responses have been ommitted for brevity. +

    From there, new certificates can reference the self-signed certificate:

    $ certutil -S -s "CN=My Server Cert" -n my-server-cert -c "my-ca-cert" -t "u,u,u" -1 -5 -6 -8 -m 730

    Generating a Certificate from a Certificate Request

    When a certificate request is created, a certificate can be generated by using the request and then referencing a certificate authority signing certificate (the issuer specified in the -c argument). The issuing certificate must be in the certificate database in the specified directory.

    certutil -C -c issuer -i cert-request-file -o output-file [-m serial-number] [-v valid-months] [-w offset-months] -d [sql:]directory [-1] [-2] [-3] [-4] [-5 keyword] [-6 keyword] [-7 emailAddress] [-8 dns-names]

    For example: -

    $ certutil -C -c "my-ca-cert" -i /home/certs/cert.req -o cert.cer -m 010 -v 12 -w 1 -d sql:/home/my/sharednssdb -1 nonRepudiation,dataEncipherment -5 sslClient -6 clientAuth -7 jsmith@example.com

    Generating Key Pairs

    - Key pairs are generated automatically with a certificate request or certificate, but they can also be generated independently using the -G command option. -

    certutil -G -d [sql:]directory | -h tokenname -k key-type -g key-size [-y exponent-value] -q pqgfile|curve-name

    - For example: -

    $ certutil -G -h lunasa -k ec -g 256 -q sect193r2

    Listing Certificates

    +

    $ certutil -C -c "my-ca-cert" -i /home/certs/cert.req -o cert.cer -m 010 -v 12 -w 1 -d sql:$HOME/nssdb -1 nonRepudiation,dataEncipherment -5 sslClient -6 clientAuth -7 jsmith@example.com

    Listing Certificates

    The -L command option lists all of the certificates listed in the certificate database. The path to the directory (-d) is required.

    $ certutil -L -d sql:/home/my/sharednssdb
     
    @@ -193,34 +172,89 @@ TPS Administrator's Example Domain ID                        u,u,u
     Google Internet Authority                                    ,,   
     Certificate Authority - Example Domain                       CT,C,C

    Using additional arguments with -L can return and print the information for a single, specific certificate. For example, the -n argument passes the certificate name, while the -a argument prints the certificate in ASCII format: -

    $ certutil -L -d sql:/home/my/sharednssdb -a -n "Certificate Authority - Example Domain"
    -
    +	

    +$ certutil -L -d sql:$HOME/nssdb -a -n my-ca-cert
     -----BEGIN CERTIFICATE-----
    -MIIDmTCCAoGgAwIBAgIBATANBgkqhkiG9w0BAQUFADA5MRcwFQYDVQQKEw5FeGFt
    -cGxlIERvbWFpbjEeMBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEw
    -MDQyOTIxNTY1OFoXDTEyMDQxODIxNTY1OFowOTEXMBUGA1UEChMORXhhbXBsZSBE
    -b21haW4xHjAcBgNVBAMTFUNlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZI
    -hvcNAQEBBQADggEPADCCAQoCggEBAO/bqUli2KwqXFKmMMG93KN1SANzNTXA/Vlf
    -Tmrih3hQgjvR1ktIY9aG6cB7DSKWmtHp/+p4PUCMqL4ZrSGt901qxkePyZ2dYmM2
    -RnelK+SEUIPiUtoZaDhNdiYsE/yuDE8vQWj0vHCVL0w72qFUcSQ/WZT7FCrnUIUI
    -udeWnoPSUn70gLhcj/lvxl7K9BHyD4Sq5CzktwYtFWLiiwV+ZY/Fl6JgbGaQyQB2
    -bP4iRMfloGqsxGuB1evWVDF1haGpFDSPgMnEPSLg3/3dXn+HDJbZ29EU8/xKzQEb
    -3V0AHKbu80zGllLEt2Zx/WDIrgJEN9yMfgKFpcmL+BvIRsmh0VsCAwEAAaOBqzCB
    -qDAfBgNVHSMEGDAWgBQATgxHQyRUfKIZtdp55bZlFr+tFzAPBgNVHRMBAf8EBTAD
    -AQH/MA4GA1UdDwEB/wQEAwIBxjAdBgNVHQ4EFgQUAE4MR0MkVHyiGbXaeeW2ZRa/
    -rRcwRQYIKwYBBQUHAQEEOTA3MDUGCCsGAQUFBzABhilodHRwOi8vbG9jYWxob3N0
    -LmxvY2FsZG9tYWluOjkxODAvY2Evb2NzcDANBgkqhkiG9w0BAQUFAAOCAQEAi8Gk
    -L3XO43u7/TDOeEsWPmq+jZsDZ3GZ85Ajt3KROLWeKVZZZa2E2Hnsvf2uXbk5amKe
    -lRxdSeRH9g85pv4KY7Z8xZ71NrI3+K3uwmnqkc6t0hhYb1mw/gx8OAAoluQx3biX
    -JBDxjI73Cf7XUopplHBjjiwyGIJUO8BEZJ5L+TF4P38MJz1snLtzZpEAX5bl0U76
    -bfu/tZFWBbE8YAWYtkCtMcalBPj6jn2WD3M01kGozW4mmbvsj1cRB9HnsGsqyHCu
    -U0ujlL1H/RWcjn607+CTeKH9jLMUqCIqPJNOa+kq/6F7NhNRRiuzASIbZc30BZ5a
    -nI7q5n1USM3eWQlVXw==
    ------END CERTIFICATE-----

    Listing Keys

    +MIIB1DCCAT2gAwIBAgICDkIwDQYJKoZIhvcNAQEFBQAwFTETMBEGA1UEAxMKRXhh +bXBsZSBDQTAeFw0xMzAzMTMxOTEwMjlaFw0xMzA2MTMxOTEwMjlaMBUxEzARBgNV +BAMTCkV4YW1wbGUgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ4Kzqvz +JyBVgFqDXRYSyTBNw1DrxUU/3GvWA/ngjAwHEv0Cul/6sO/gsCvnABHiH6unns6x +XRzPORlC2WY3gkk7vmlsLvYpyecNazAi/NAwVnU/66HOsaoVFWE+gBQo99UrN2yk +0BiK/GMFlLm5dXQROgA9ZKKyFdI0LIXtf6SbAgMBAAGjMzAxMBEGCWCGSAGG+EIB +AQQEAwIHADAMBgNVHRMEBTADAQH/MA4GA1UdDwEB/wQEAwICBDANBgkqhkiG9w0B +AQUFAAOBgQA6chkzkACN281d1jKMrc+RHG2UMaQyxiteaLVZO+Ro1nnRUvseDf09 +XKYFwPMJjWCihVku6bw/ihZfuMHhxK22Nue6inNQ6eDu7WmrqL8z3iUrQwxs+WiF +ob2rb8XRVVJkzXdXxlk4uo3UtNvw8sAz7sWD71qxKaIHU5q49zijfg== +-----END CERTIFICATE----- +

    For a human-readable display

    $ certutil -L -d sql:$HOME/nssdb -n my-ca-cert
    +Certificate:
    +    Data:
    +        Version: 3 (0x2)
    +        Serial Number: 3650 (0xe42)
    +        Signature Algorithm: PKCS #1 SHA-1 With RSA Encryption
    +        Issuer: "CN=Example CA"
    +        Validity:
    +            Not Before: Wed Mar 13 19:10:29 2013
    +            Not After : Thu Jun 13 19:10:29 2013
    +        Subject: "CN=Example CA"
    +        Subject Public Key Info:
    +            Public Key Algorithm: PKCS #1 RSA Encryption
    +            RSA Public Key:
    +                Modulus:
    +                    9e:0a:ce:ab:f3:27:20:55:80:5a:83:5d:16:12:c9:30:
    +                    4d:c3:50:eb:c5:45:3f:dc:6b:d6:03:f9:e0:8c:0c:07:
    +                    12:fd:02:ba:5f:fa:b0:ef:e0:b0:2b:e7:00:11:e2:1f:
    +                    ab:a7:9e:ce:b1:5d:1c:cf:39:19:42:d9:66:37:82:49:
    +                    3b:be:69:6c:2e:f6:29:c9:e7:0d:6b:30:22:fc:d0:30:
    +                    56:75:3f:eb:a1:ce:b1:aa:15:15:61:3e:80:14:28:f7:
    +                    d5:2b:37:6c:a4:d0:18:8a:fc:63:05:94:b9:b9:75:74:
    +                    11:3a:00:3d:64:a2:b2:15:d2:34:2c:85:ed:7f:a4:9b
    +                Exponent: 65537 (0x10001)
    +        Signed Extensions:
    +            Name: Certificate Type
    +            Data: none
    +
    +            Name: Certificate Basic Constraints
    +            Data: Is a CA with no maximum path length.
    +
    +            Name: Certificate Key Usage
    +            Critical: True
    +            Usages: Certificate Signing
    +
    +    Signature Algorithm: PKCS #1 SHA-1 With RSA Encryption
    +    Signature:
    +        3a:72:19:33:90:00:8d:db:cd:5d:d6:32:8c:ad:cf:91:
    +        1c:6d:94:31:a4:32:c6:2b:5e:68:b5:59:3b:e4:68:d6:
    +        79:d1:52:fb:1e:0d:fd:3d:5c:a6:05:c0:f3:09:8d:60:
    +        a2:85:59:2e:e9:bc:3f:8a:16:5f:b8:c1:e1:c4:ad:b6:
    +        36:e7:ba:8a:73:50:e9:e0:ee:ed:69:ab:a8:bf:33:de:
    +        25:2b:43:0c:6c:f9:68:85:a1:bd:ab:6f:c5:d1:55:52:
    +        64:cd:77:57:c6:59:38:ba:8d:d4:b4:db:f0:f2:c0:33:
    +        ee:c5:83:ef:5a:b1:29:a2:07:53:9a:b8:f7:38:a3:7e
    +    Fingerprint (MD5):
    +        86:D8:A5:8B:8A:26:BE:9E:17:A8:7B:66:10:6B:27:80
    +    Fingerprint (SHA1):
    +        48:78:09:EF:C5:D4:0C:BD:D2:64:45:59:EB:03:13:15:F7:A9:D6:F7
    +
    +    Certificate Trust Flags:
    +        SSL Flags:
    +            Valid CA
    +            Trusted CA
    +            User
    +        Email Flags:
    +            Valid CA
    +            Trusted CA
    +            User
    +        Object Signing Flags:
    +            Valid CA
    +            Trusted CA
    +            User
    +
    +

    Listing Keys

    Keys are the original material used to encrypt certificate data. The keys generated for certificates are stored separately, in the key database.

    To list all keys in the database, use the -K command option and the (required) -d argument to give the path to the directory. -

    $ certutil -K -d sql:/home/my/sharednssdb
    +	

    $ certutil -K -d sql:$HOME/nssdb
     certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services                  "
     < 0> rsa      455a6673bde9375c2887ec8bf8016b3f9f35861d   Thawte Freemail Member's Thawte Consulting (Pty) Ltd. ID
     < 1> rsa      40defeeb522ade11090eacebaaf1196a172127df   Example Domain Administrator Cert
    @@ -291,12 +325,12 @@ The last versions of these legacy databas
     		

    BerkeleyDB has performance limitations, though, which prevent it from being easily used by multiple applications simultaneously. NSS has some flexibility that allows applications to use their own, independent database engine while keeping a shared database and working around the access issues. Still, NSS requires more flexibility to provide a truly shared security database.

    In 2009, NSS introduced a new set of databases that are SQLite databases rather than -BerkleyDB. These new databases provide more accessibility and performance:

    • +BerkeleyDB. These new databases provide more accessibility and performance:

      • cert9.db for certificates

      • key4.db for keys

      • - pkcs11.txt, which is listing of all of the PKCS #11 modules contained in a new subdirectory in the security databases directory + pkcs11.txt, a listing of all of the PKCS #11 modules, contained in a new subdirectory in the security databases directory

      Because the SQLite databases are designed to be shared, these are the shared database type. The shared database type is preferred; the legacy format is included for backward compatibility.

      By default, the tools (certutil, pk12util, modutil) assume that the given security databases follow the more common legacy type. Using the SQLite databases must be manually specified by using the sql: prefix with the given security directory. For example:

      $ certutil -L -d sql:/home/my/sharednssdb

      To set the shared database type as the default type for the tools, set the NSS_DEFAULT_DB_TYPE environment variable to sql:

      export NSS_DEFAULT_DB_TYPE="sql"

      This line can be set added to the ~/.bashrc file to make the change permanent.

      Most applications do not use the shared database by default, but they can be configured to use them. For example, this how-to article covers how to configure Firefox and Thunderbird to use the new shared NSS databases:

      • https://wiki.mozilla.org/NSS_Shared_DB_Howto

      For an engineering draft on the changes in the shared NSS databases, see the NSS project wiki:

      • @@ -310,9 +344,7 @@ Using the SQLite databases must be manually specified by using the

        • https://wiki.mozilla.org/NSS_Shared_DB_Howto

        • https://wiki.mozilla.org/NSS_Shared_DB -

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/cmsutil.html b/security/nss/doc/html/cmsutil.html index ac5ea6b9488..2b5249cadcd 100644 --- a/security/nss/doc/html/cmsutil.html +++ b/security/nss/doc/html/cmsutil.html @@ -1,4 +1,4 @@ -CMSUTIL

    Name

    cmsutil — Performs basic cryptograpic operations, such as encryption and decryption, on Cryptographic Message Syntax (CMS) messages.

    Synopsis

    cmsutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +CMSUTIL

    Name

    cmsutil — Performs basic cryptograpic operations, such as encryption and decryption, on Cryptographic Message Syntax (CMS) messages.

    Synopsis

    cmsutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The cmsutil command-line uses the S/MIME Toolkit to perform basic operations, such as encryption and decryption, on Cryptographic Message Syntax (CMS) messages.

    To run cmsutil, type the command cmsutil option [arguments] where option and arguments are combinations of the options and arguments listed in the following section. @@ -8,10 +8,10 @@ To see a usage string, issue the command without options.

    Options

    Options specify an action. Option arguments modify an action. The options and arguments for the cmsutil command are defined as follows: -

    -D

    Decode a message.

    -C

    Encrypt a message.

    -E

    Envelope a message.

    -O

    Create a certificates-only message.

    -S

    Sign a message.

    Arguments

    Option arguments modify an action and are lowercase.

    -c content

    Use this detached content (decode only).

    -d dbdir

    Specify the key/certificate database directory (default is ".")

    -e envfile

    Specify a file containing an enveloped message for a set of recipients to which you would like to send an encrypted message. If this is the first encrypted message for that set of recipients, a new enveloped message will be created that you can then use for future messages (encrypt only).

    -G

    Include a signing time attribute (sign only).

    -h num

    Generate email headers with info about CMS message (decode only).

    -i infile

    Use infile as a source of data (default is stdin).

    -N nickname

    Specify nickname of certificate to sign with (sign only).

    -n

    Suppress output of contents (decode only).

    -o outfile

    Use outfile as a destination of data (default is stdout).

    -P

    Include an S/MIME capabilities attribute.

    -p password

    Use password as key database password.

    -r recipient1,recipient2, ...

    +

    -D

    Decode a message.

    -C

    Encrypt a message.

    -E

    Envelope a message.

    -O

    Create a certificates-only message.

    -S

    Sign a message.

    Arguments

    Option arguments modify an action.

    -b

    Decode a batch of files named in infile.

    -c content

    Use this detached content (decode only).

    -d dbdir

    Specify the key/certificate database directory (default is ".")

    -e envfile

    Specify a file containing an enveloped message for a set of recipients to which you would like to send an encrypted message. If this is the first encrypted message for that set of recipients, a new enveloped message will be created that you can then use for future messages (encrypt only).

    -f pwfile

    Use password file to set password on all PKCS#11 tokens.

    -G

    Include a signing time attribute (sign only).

    -H hash

    Use specified hash algorithm (default:SHA1).

    -h num

    Generate email headers with info about CMS message (decode only).

    -i infile

    Use infile as a source of data (default is stdin).

    -k

    Keep decoded encryption certs in permanent cert db.

    -N nickname

    Specify nickname of certificate to sign with (sign only).

    -n

    Suppress output of contents (decode only).

    -o outfile

    Use outfile as a destination of data (default is stdout).

    -P

    Include an S/MIME capabilities attribute.

    -p password

    Use password as key database password.

    -r recipient1,recipient2, ...

    Specify list of recipients (email addresses) for an encrypted or enveloped message. For certificates-only message, list of certificates to send. -

    -T

    Suppress content in CMS message (sign only).

    -u certusage

    Set type of cert usage (default is certUsageEmailSigner).

    -Y ekprefnick

    Specify an encryption key preference by nickname.

    Usage

    Encrypt Example

    +          

    -T

    Suppress content in CMS message (sign only).

    -u certusage

    Set type of cert usage (default is certUsageEmailSigner).

    -v

    Print debugging information.

    -Y ekprefnick

    Specify an encryption key preference by nickname.

    Usage

    Encrypt Example

     cmsutil -C [-i infile] [-o outfile] [-d dbdir] [-p password] -r "recipient1,recipient2, . . ." -e envfile
           

    Decode Example

     cmsutil -D [-i infile] [-o outfile] [-d dbdir] [-p password] [-c content] [-n] [-h num]
    @@ -21,12 +21,10 @@ cmsutil -E [-i infile] [-o outfile] [-d dbdir] [-p password] -r "recipient1,reci
     cmsutil -O [-i infile] [-o outfile] [-d dbdir] [-p password] -r "cert1,cert2, . . ."
           

    Sign Message Example

     cmsutil -S [-i infile] [-o outfile] [-d dbdir] [-p password] -N nickname[-TGP] [-Y ekprefnick]
    -      

    See also

    certutil(1)

    See Also

    +

    See also

    certutil(1)

    See Also

    -

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/crlutil.html b/security/nss/doc/html/crlutil.html index 0b36ffc9fbc..3f39545e6b8 100644 --- a/security/nss/doc/html/crlutil.html +++ b/security/nss/doc/html/crlutil.html @@ -1,6 +1,6 @@ -CRLUTIL

    Name

    crlutil — +CRLUTIL

    Name

    crlutil — List, generate, modify, or delete CRLs within the NSS security database file(s) and list, create, modify or delete certificates entries in a particular CRL. -

    Synopsis

    crlutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +

    Synopsis

    crlutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The Certificate Revocation List (CRL) Management Tool, crlutil, is a command-line utility that can list, generate, modify, or delete CRLs within the NSS security database file(s) and list, create, modify or delete certificates entries in a particular CRL.

    The key and certificate management process generally begins with creating keys in the key database, then generating and managing certificates in the certificate database(see certutil tool) and continues with certificates expiration or revocation. @@ -58,7 +58,7 @@ Specify the output file name for new CRL. Bracket the output-file string with qu Specify type of CRL. possible types are: 0 - SEC_KRL_TYPE, 1 - SEC_CRL_TYPE. This option is obsolete

    -u url

    Specify the url. -

    CRL Generation script syntax

    CRL generation script file has the following syntax:

    +

    -w pwd-string

    Provide db password in command line.

    -Z algorithm

    Specify the hash algorithm to use for signing the CRL.

    CRL Generation script syntax

    CRL generation script file has the following syntax:

    * Line with comments should have # as a first symbol of a line

    * Set "this update" or "next update" CRL fields:

    @@ -200,12 +200,10 @@ crlutil -G|-M -c crl-gen-file -n nickname [-i crl] [-u url] [-d keydir] [-P dbpr * Import CRL from file:

               crlutil -I -i crl [-t crlType] [-u url] [-d keydir] [-P dbprefix] [-B] 
    -    

    See also

    certutil(1)

    See Also

    +

    See also

    certutil(1)

    See Also

    -

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/modutil.html b/security/nss/doc/html/modutil.html index 37a6e42cdae..2d16199c4b1 100644 --- a/security/nss/doc/html/modutil.html +++ b/security/nss/doc/html/modutil.html @@ -1,4 +1,4 @@ -MODUTIL

    Name

    modutil — Manage PKCS #11 module information within the security module database.

    Synopsis

    modutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +MODUTIL

    Name

    modutil — Manage PKCS #11 module information within the security module database.

    Synopsis

    modutil [options] [[arguments]]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The Security Module Database Tool, modutil, is a command-line utility for managing PKCS #11 module information both within secmod.db files and within hardware tokens. modutil can add and delete PKCS #11 modules, change passwords on security databases, set defaults, list module contents, enable or disable slots, enable or disable FIPS 140-2 compliance, and assign default providers for cryptographic operations. This tool can also create certificate, key, and module security database files.

    The tasks associated with security module database management are part of a process that typically also involves managing key databases and certificate databases.

    Options

    Running modutil always requires one (and only one) option to specify the type of module operation. Each option may take arguments, anywhere from none to multiple arguments.

    Options

    -add modulename

    Add the named PKCS #11 module to the database. Use this option with the -libfile, -ciphers, and -mechanisms arguments.

    -changepw tokenname

    Change the password on the named token. If the token has not been initialized, this option initializes the password. Use this option with the -pwfile and -newpwfile arguments. A password is equivalent to a personal identification number (PIN).

    -chkfips

    Verify whether the module is in the given FIPS mode. true means to verify that the module is in FIPS mode, while false means to verify that the module is not in FIPS mode.

    -create

    Create new certificate, key, and module databases. Use the -dbdir directory argument to specify a directory. If any of these databases already exist in a specified directory, modutil returns an error message.

    -default modulename

    Specify the security mechanisms for which the named module will be a default provider. The security mechanisms are specified with the -mechanisms argument.

    -delete modulename

    Delete the named module. The default NSS PKCS #11 module cannot be deleted.

    -disable modulename

    Disable all slots on the named module. Use the -slot argument to disable a specific slot.

    -enable modulename

    Enable all slots on the named module. Use the -slot argument to enable a specific slot.

    -fips [true | false]

    Enable (true) or disable (false) FIPS 140-2 compliance for the default NSS module.

    -force

    Disable modutil's interactive prompts so it can be run from a script. Use this option only after manually testing each planned operation to check for warnings and to ensure that bypassing the prompts will cause no security lapses or loss of database integrity.

    -jar JAR-file

    Add a new PKCS #11 module to the database using the named JAR file. Use this command with the -installdir and -tempdir arguments. The JAR file uses the NSS PKCS #11 JAR format to identify all the files to be installed, the module's name, the mechanism flags, and the cipher flags, as well as any files to be installed on the target machine, including the PKCS #11 module library file and other files such as documentation. This is covered in the JAR installation file section in the man page, which details the special script needed to perform an installation through a server or with modutil.

    -list [modulename]

    Display basic information about the contents of the secmod.db file. Specifying a modulename displays detailed information about a particular module and its slots and tokens.

    -rawadd

    Add the module spec string to the secmod.db database.

    -rawlist

    Display the module specs for a specified module or for all loadable modules.

    -undefault modulename

    Specify the security mechanisms for which the named module will not be a default provider. The security mechanisms are specified with the -mechanisms argument.

    Arguments

    MODULE

    Give the security module to access.

    MODULESPEC

    Give the security module spec to load into the security database.

    -ciphers cipher-enable-list

    Enable specific ciphers in a module that is being added to the database. The cipher-enable-list is a colon-delimited list of cipher names. Enclose this list in quotation marks if it contains spaces.

    -dbdir [sql:]directory

    Specify the database directory in which to access or create security module database files.

    modutil supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    --dbprefix prefix

    Specify the prefix used on the database files, such as my_ for my_cert8.db. This option is provided as a special case. Changing the names of the certificate and key databases is not recommended.

    -installdir root-installation-directory

    Specify the root installation directory relative to which files will be installed by the -jar option. This directory should be one below which it is appropriate to store dynamic library files, such as a server's root directory.

    -libfile library-file

    Specify a path to a library file containing the implementation of the PKCS #11 interface module that is being added to the database.

    -mechanisms mechanism-list

    Specify the security mechanisms for which a particular module will be flagged as a default provider. The mechanism-list is a colon-delimited list of mechanism names. Enclose this list in quotation marks if it contains spaces.

    The module becomes a default provider for the listed mechanisms when those mechanisms are enabled. If more than one module claims to be a particular mechanism's default provider, that mechanism's default provider is undefined.

    modutil supports several mechanisms: RSA, DSA, RC2, RC4, RC5, AES, DES, DH, SHA1, SHA256, SHA512, SSL, TLS, MD5, MD2, RANDOM (for random number generation), and FRIENDLY (meaning certificates are publicly readable).

    -newpwfile new-password-file

    Specify a text file containing a token's new or replacement password so that a password can be entered automatically with the -changepw option.

    -nocertdb

    Do not open the certificate or key databases. This has several effects:

    • With the -create command, only a module security file is created; certificate and key databases are not created.

    • With the -jar command, signatures on the JAR file are not checked.

    • With the -changepw command, the password on the NSS internal module cannot be set or changed, since this password is stored in the key database.

    -pwfile old-password-file

    Specify a text file containing a token's existing password so that a password can be entered automatically when the -changepw option is used to change passwords.

    -secmod secmodname

    Give the name of the security module database (like secmod.db) to load.

    -slot slotname

    Specify a particular slot to be enabled or disabled with the -enable or -disable options.

    -string CONFIG_STRING

    Pass a configuration string for the module being added to the database.

    -tempdir temporary-directory

    Give a directory location where temporary files are created during the installation by the -jar option. If no temporary directory is specified, the current directory is used.

    Usage and Examples

    Creating Database Files

    Before any operations can be performed, there must be a set of security databases available. modutil can be used to create these files. The only required argument is the database that where the databases will be located.

    modutil -create -dbdir [sql:]directory

    Adding a Cryptographic Module

    Adding a PKCS #11 module means submitting a supporting library file, enabling its ciphers, and setting default provider status for various security mechanisms. This can be done by supplying all of the information through modutil directly or by running a JAR file and install script. For the most basic case, simply upload the library:

    modutil -add modulename -libfile library-file [-ciphers cipher-enable-list] [-mechanisms mechanism-list] 

    For example: @@ -242,9 +242,7 @@ Using the SQLite databases must be manually specified by using the

    See Also

    certutil (1)

    pk12util (1)

    signtool (1)

    The NSS wiki has information on the new database design and how to configure applications to use it.

    • https://wiki.mozilla.org/NSS_Shared_DB_Howto

    • https://wiki.mozilla.org/NSS_Shared_DB -

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/pk12util.html b/security/nss/doc/html/pk12util.html index e13a31d9aa4..e943bad368d 100644 --- a/security/nss/doc/html/pk12util.html +++ b/security/nss/doc/html/pk12util.html @@ -1,10 +1,10 @@ -PK12UTIL

    Name

    pk12util — Export and import keys and certificate to or from a PKCS #12 file and the NSS database

    Synopsis

    pk12util [-i p12File [-h tokenname] [-v] [common-options] ] [ +PK12UTIL

    Name

    pk12util — Export and import keys and certificate to or from a PKCS #12 file and the NSS database

    Synopsis

    pk12util [-i p12File [-h tokenname] [-v] [common-options] ] [ -l p12File [-h tokenname] [-r] [common-options] ] [ -o p12File -n certname [-c keyCipher] [-C certCipher] [-m|--key_len keyLen] [-n|--cert_key_len certKeyLen] [common-options] ] [ common-options are: [-d [sql:]directory] [-P dbprefix] [-k slotPasswordFile|-K slotPassword] [-w p12filePasswordFile|-W p12filePassword] - ]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 + ]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The PKCS #12 utility, pk12util, enables sharing certificates among any server that supports PKCS#12. The tool can import certificates and keys from PKCS#12 files into security databases, export certificates, and list certificates and keys.

    Options and Arguments

    Options

    -i p12file

    Import keys and certificates from a PKCS#12 file into a security database.

    -l p12file

    List the keys and certificates in PKCS#12 file.

    -o p12file

    Export keys and certificates from the security database to a PKCS#12 file.

    Arguments

    -n certname

    Specify the nickname of the cert and private key to export.

    -d [sql:]directory

    Specify the database directory into which to import to or export from certificates and keys.

    pk12util supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    -P prefix

    Specify the prefix used on the certificate and key databases. This option is provided as a special case. Changing the names of the certificate and key databases is not recommended.

    -h tokenname

    Specify the name of the token to import into or export from.

    -v

    Enable debug logging when importing.

    -k slotPasswordFile

    Specify the text file containing the slot's password.

    -K slotPassword

    Specify the slot's password.

    -w p12filePasswordFile

    Specify the text file containing the pkcs #12 file password.

    -W p12filePassword

    Specify the pkcs #12 file password.

    -c keyCipher

    Specify the key encryption algorithm.

    -C certCipher

    Specify the key cert (overall package) encryption algorithm.

    -m | --key-len keyLength

    Specify the desired length of the symmetric key to be used to encrypt the private key.

    -n | --cert-key-len certKeyLength

    Specify the desired length of the symmetric key to be used to encrypt the certificates and other meta-data.

    -r

    Dumps all of the data in raw (binary) form. This must be saved as a DER file. The default is to return information in a pretty-print ASCII format, which displays the information about the certificates and public keys in the p12 file.

    Return Codes

    • 0 - No error

    • 1 - User Cancelled

    • 2 - Usage error

    • 6 - NLS init error

    • 8 - Certificate DB open error

    • 9 - Key DB open error

    • 10 - File initialization error

    • 11 - Unicode conversion error

    • 12 - Temporary file creation error

    • 13 - PKCS11 get slot error

    • 14 - PKCS12 decoder start error

    • 15 - error read from import file

    • 16 - pkcs12 decode error

    • 17 - pkcs12 decoder verify error

    • 18 - pkcs12 decoder validate bags error

    • 19 - pkcs12 decoder import bags error

    • 20 - key db conversion version 3 to version 2 error

    • 21 - cert db conversion version 7 to version 5 error

    • 22 - cert and key dbs patch error

    • 23 - get default cert db error

    • 24 - find cert by nickname error

    • 25 - create export context error

    • 26 - PKCS12 add password itegrity error

    • 27 - cert and key Safes creation error

    • 28 - PKCS12 add cert and key error

    • 29 - PKCS12 encode error

    Examples

    Importing Keys and Certificates

    The most basic usage of pk12util for importing a certificate or key is the PKCS#12 input file (-i) and some way to specify the security database being accessed (either -d for a directory or -h for a token).

    pk12util -i p12File [-h tokenname] [-v] [-d [sql:]directory] [-P dbprefix] [-k slotPasswordFile|-K slotPassword] [-w p12filePasswordFile|-W p12filePassword]

    For example:

    # pk12util -i /tmp/cert-files/users.p12 -d sql:/home/my/sharednssdb
    @@ -74,9 +74,7 @@ Using the SQLite databases must be manually specified by using the 

    See Also

    certutil (1)

    modutil (1)

    The NSS wiki has information on the new database design and how to configure applications to use it.

    • https://wiki.mozilla.org/NSS_Shared_DB_Howto

    • https://wiki.mozilla.org/NSS_Shared_DB -

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/pp.html b/security/nss/doc/html/pp.html index b613520ad42..e03902f310a 100644 --- a/security/nss/doc/html/pp.html +++ b/security/nss/doc/html/pp.html @@ -1,9 +1,7 @@ -PP

    Name

    pp — Prints certificates, keys, crls, and pkcs7 files

    Synopsis

    pp -t type [-a] [-i input] [-o output]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 -

    Description

    pp pretty-prints private and public key, certificate, certificate-request, +PP

    Name

    pp — Prints certificates, keys, crls, and pkcs7 files

    Synopsis

    pp -t type [-a] [-i input] [-o output]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +

    Description

    pp pretty-prints private and public key, certificate, certificate-request, pkcs7 or crl files -

    Options

    -t type

    specify the input, one of {private-key | public-key | certificate | certificate-request | pkcs7 | crl}

    -a
    Input is in ascii encoded form (RFC1113)
    -i inputfile
    Define an input file to use (default is stdin)
    -u outputfile
    Define an output file to use (default is stdout)

    Additional Resources

    NSS is maintained in conjunction with PKI and security-related projects through Mozilla dn Fedora. The most closely-related project is Dogtag PKI, with a project wiki at PKI Wiki.

    For information specifically about NSS, the NSS project wiki is located at Mozilla NSS site. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: pki-devel@redhat.com and pki-users@redhat.com

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Options

    -t type

    specify the input, one of {private-key | public-key | certificate | certificate-request | pkcs7 | crl}

    -a
    Input is in ascii encoded form (RFC1113)
    -i inputfile
    Define an input file to use (default is stdin)
    -u outputfile
    Define an output file to use (default is stdout)

    Additional Resources

    NSS is maintained in conjunction with PKI and security-related projects through Mozilla and Fedora. The most closely-related project is Dogtag PKI, with a project wiki at PKI Wiki.

    For information specifically about NSS, the NSS project wiki is located at Mozilla NSS site. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: pki-devel@redhat.com and pki-users@redhat.com

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/signtool.html b/security/nss/doc/html/signtool.html index 8d762139a1c..9fb932c38b1 100644 --- a/security/nss/doc/html/signtool.html +++ b/security/nss/doc/html/signtool.html @@ -1,4 +1,4 @@ -signtool

    Name

    signtool — Digitally sign objects and files.

    Synopsis

    signtool [-k keyName] [[-h]] [[-H]] [[-l]] [[-L]] [[-M]] [[-v]] [[-w]] [[-G nickname]] [[--keysize | -s size]] [[-b basename]] [[-c Compression Level] ] [[-d cert-dir] ] [[-i installer script] ] [[-m metafile] ] [[-x name] ] [[-f filename] ] [[-t|--token tokenname] ] [[-e extension] ] [[-o] ] [[-z] ] [[-X] ] [[--outfile] ] [[--verbose value] ] [[--norecurse] ] [[--leavearc] ] [[-j directory] ] [[-Z jarfile] ] [[-O] ] [[-p password] ] [directory-tree] [archive]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +signtool

    Name

    signtool — Digitally sign objects and files.

    Synopsis

    signtool [-k keyName] [[-h]] [[-H]] [[-l]] [[-L]] [[-M]] [[-v]] [[-w]] [[-G nickname]] [[--keysize | -s size]] [[-b basename]] [[-c Compression Level] ] [[-d cert-dir] ] [[-i installer script] ] [[-m metafile] ] [[-x name] ] [[-f filename] ] [[-t|--token tokenname] ] [[-e extension] ] [[-o] ] [[-z] ] [[-X] ] [[--outfile] ] [[--verbose value] ] [[--norecurse] ] [[--leavearc] ] [[-j directory] ] [[-Z jarfile] ] [[-O] ] [[-p password] ] [directory-tree] [archive]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The Signing Tool, signtool, creates digital signatures and uses a Java Archive (JAR) file to associate the signatures with files in a directory. Electronic software distribution over any network involves potential security problems. To help address some of these problems, you can associate digital signatures with the files in a JAR archive. Digital signatures allow SSL-enabled clients to perform two important operations:

    * Confirm the identity of the individual, company, or other entity whose digital signature is associated with the files

    * Check whether the files have been tampered with since being signed

    If you have a signing certificate, you can use Netscape Signing Tool to digitally sign files and package them as a JAR file. An object-signing certificate is a special kind of certificate that allows you to associate your digital signature with one or more files.

    An individual file can potentially be signed with multiple digital signatures. For example, a commercial software developer might sign the files that constitute a software product to prove that the files are indeed from a particular company. A network administrator manager might sign the same files with an additional digital signature based on a company-generated certificate to indicate that the product is approved for use within the company.

    The significance of a digital signature is comparable to the significance of a handwritten signature. Once you have signed a file, it is difficult to claim later that you didn't sign it. In some situations, a digital signature may be considered as legally binding as a handwritten signature. Therefore, you should take great care to ensure that you can stand behind any file you sign and distribute.

    For example, if you are a software developer, you should test your code to make sure it is virus-free before signing it. Similarly, if you are a network administrator, you should make sure, before signing any code, that it comes from a reliable source and will run correctly with the software installed on the machines to which you are distributing it.

    Before you can use Netscape Signing Tool to sign files, you must have an object-signing certificate, which is a special certificate whose associated private key is used to create digital signatures. For testing purposes only, you can create an object-signing certificate with Netscape Signing Tool 1.3. When testing is finished and you are ready to disitribute your software, you should obtain an object-signing certificate from one of two kinds of sources:

    * An independent certificate authority (CA) that authenticates your identity and charges you a fee. You typically get a certificate from an independent CA if you want to sign software that will be distributed over the Internet.

    * CA server software running on your corporate intranet or extranet. Netscape Certificate Management System provides a complete management solution for creating, deploying, and managing certificates, including CAs that issue object-signing certificates.

    You must also have a certificate for the CA that issues your signing certificate before you can sign files. If the certificate authority's certificate isn't already installed in your copy of Communicator, you typically install it by clicking the appropriate link on the certificate authority's web site, for example on the page from which you initiated enrollment for your signing certificate. This is the case for some test certificates, as well as certificates issued by Netscape Certificate Management System: you must download the the CA certificate in addition to obtaining your own signing certificate. CA certificates for several certificate authorities are preinstalled in the Communicator certificate database.

    When you receive an object-signing certificate for your own use, it is automatically installed in your copy of the Communicator client software. Communicator supports the public-key cryptography standard known as PKCS #12, which governs key portability. You can, for example, move an object-signing certificate and its associated private key from one computer to another on a credit-card-sized device called a smart card.

    Options

    -b basename

    Specifies the base filename for the .rsa and .sf files in the META-INF directory to conform with the JAR format. For example, -b signatures causes the files to be named signatures.rsa and signatures.sf. The default is signtool.

    -c#

    Specifies the compression level for the -J or -Z option. The symbol # represents a number from 0 to 9, where 0 means no compression and 9 means maximum compression. The higher the level of compression, the smaller the output but the longer the operation takes. @@ -278,9 +278,7 @@ token: Communicator Certificate DB -----------------------------------------------

    See Also

    signver (1)

    The NSS wiki has information on the new database design and how to configure applications to use it.

    • https://wiki.mozilla.org/NSS_Shared_DB_Howto

    • https://wiki.mozilla.org/NSS_Shared_DB -

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/signver.html b/security/nss/doc/html/signver.html index 7af22ce2e6f..4f0a9c3c6f5 100644 --- a/security/nss/doc/html/signver.html +++ b/security/nss/doc/html/signver.html @@ -1,7 +1,7 @@ -SIGNVER

    Name

    signver — Verify a detached PKCS#7 signature for a file.

    Synopsis

    signtool -A | -V -d directory [-a] [-i input_file] [-o output_file] [-s signature_file] [-v]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 -

    Description

    The Signature Verification Tool, signver, is a simple command-line utility that unpacks a base-64-encoded PKCS#7 signed object and verifies the digital signature using standard cryptographic techniques. The Signature Verification Tool can also display the contents of the signed object.

    Options

    -A

    Displays all of the information in the PKCS#7 signature.

    -V

    Verifies the digital signature.

    -d [sql:]directory

    Specify the database directory which contains the certificates and keys.

    signver supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    -a

    Sets that the given signature file is in ASCII format.

    -i input_file

    Gives the input file for the object with signed data.

    -o output_file

    Gives the output file to which to write the results.

    -s signature_file

    Gives the input file for the digital signature.

    -v

    Enables verbose output.

    Extended Examples

    Verifying a Signature

    The -V option verifies that the signature in a given signature file is valid when used to sign the given object (from the input file).

    signver -V -s signature_file -i signed_file -d sql:/home/my/sharednssdb
    +SIGNVER

    Name

    signver — Verify a detached PKCS#7 signature for a file.

    Synopsis

    signtool -A | -V -d directory [-a] [-i input_file] [-o output_file] [-s signature_file] [-v]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +

    Description

    The Signature Verification Tool, signver, is a simple command-line utility that unpacks a base-64-encoded PKCS#7 signed object and verifies the digital signature using standard cryptographic techniques. The Signature Verification Tool can also display the contents of the signed object.

    Options

    -A

    Displays all of the information in the PKCS#7 signature.

    -V

    Verifies the digital signature.

    -d [sql:]directory

    Specify the database directory which contains the certificates and keys.

    signver supports two types of databases: the legacy security databases (cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db, key4.db, and pkcs11.txt). If the prefix sql: is not used, then the tool assumes that the given databases are in the old format.

    -a

    Sets that the given signature file is in ASCII format.

    -i input_file

    Gives the input file for the object with signed data.

    -o output_file

    Gives the output file to which to write the results.

    -s signature_file

    Gives the input file for the digital signature.

    -v

    Enables verbose output.

    Extended Examples

    Verifying a Signature

    The -V option verifies that the signature in a given signature file is valid when used to sign the given object (from the input file).

    signver -V -s signature_file -i signed_file -d sql:/home/my/sharednssdb
     
    -signatureValid=yes

    Printing Signature Data

    +signatureValid=yes

    Printing Signature Data

    The -A option prints all of the information contained in a signature file. Using the -o option prints the signature file information to the given output file rather than stdout.

    signver -A -s signature_file -o output_file

    NSS Database Types

    NSS originally used BerkeleyDB databases to store security information. The last versions of these legacy databases are:

    • @@ -27,9 +27,7 @@ Using the SQLite databases must be manually specified by using the

      Additional Resources

      For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

      Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

      IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/ssltap.html b/security/nss/doc/html/ssltap.html index 48b77920b4c..a3e9b911308 100644 --- a/security/nss/doc/html/ssltap.html +++ b/security/nss/doc/html/ssltap.html @@ -1,4 +1,4 @@ -SSLTAP

    Name

    ssltap — Tap into SSL connections and display the data going by

    Synopsis

    libssltap [-vhfsxl] [-p port] [hostname:port]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +SSLTAP

    Name

    ssltap — Tap into SSL connections and display the data going by

    Synopsis

    libssltap [-vhfsxl] [-p port] [hostname:port]

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The SSL Debugging Tool ssltap is an SSL-aware command-line proxy. It watches TCP connections and displays the data going by. If a connection is SSL, the data display includes interpreted SSL records and handshaking

    Options

    -v

    Print a version string for the tool.

    -h

    Turn on hex/ASCII printing. Instead of outputting raw data, the command interprets each record as a numbered line of hex values, followed by the same data as ASCII characters. The two parts are separated by a vertical bar. Nonprinting characters are replaced by dots.

    -f

    @@ -414,9 +414,7 @@ If you run the tool on a machine other than the SSL server to which you are tryi the browser will complain that the host name you are trying to connect to is different from the certificate. If you are using the default BadCert callback, you can still connect through a dialog. If you are not using the default BadCert callback, the one you supply must allow for this possibility. -

    See Also

    The NSS Security Tools are also documented at http://www.mozilla.org/projects/security/pki/nss/.

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    See Also

    The NSS Security Tools are also documented at http://www.mozilla.org/projects/security/pki/nss/.

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/vfychain.html b/security/nss/doc/html/vfychain.html index d33003fbacb..6d62b9ad3b8 100644 --- a/security/nss/doc/html/vfychain.html +++ b/security/nss/doc/html/vfychain.html @@ -1,4 +1,4 @@ -VFYCHAIN

    Name

    vfychain — vfychain [options] [revocation options] certfile [[options] certfile] ...

    Synopsis

    vfychain

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +VFYCHAIN

    Name

    vfychain — vfychain [options] [revocation options] certfile [[options] certfile] ...

    Synopsis

    vfychain

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477

    Description

    The verification Tool, vfychain, verifies certificate chains. modutil can add and delete PKCS #11 modules, change passwords on security databases, set defaults, list module contents, enable or disable slots, enable or disable FIPS 140-2 compliance, and assign default providers for cryptographic operations. This tool can also create certificate, key, and module security database files.

    The tasks associated with security module database management are part of a process that typically also involves managing key databases and certificate databases.

    Options

    -a
    the following certfile is base64 encoded
    -b YYMMDDHHMMZ
    Validate date (default: now)
    -d directory
    database directory
    -f
    Enable cert fetching from AIA URL
    -o oid
    Set policy OID for cert validation(Format OID.1.2.3)
    -p

    Use PKIX Library to validate certificate by calling:

    * CERT_VerifyCertificate if specified once,

    * CERT_PKIXVerifyCert if specified twice and more.

    -r
    Following certfile is raw binary DER (default)
    -t
    Following cert is explicitly trusted (overrides db trust)
    -u usage

    0=SSL client, 1=SSL server, 2=SSL StepUp, 3=SSL CA, 4=Email signer, 5=Email recipient, 6=Object signer, @@ -20,9 +20,7 @@

    -s method flags
    Sets revocation flags for the method it follows. Possible types are "doNotUse", "forbidFetching", "ignoreDefaultSrc", "requireInfo" and "failIfNoInfo". -

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/html/vfyserv.html b/security/nss/doc/html/vfyserv.html index 331cf81ead4..e7cef7a6676 100644 --- a/security/nss/doc/html/vfyserv.html +++ b/security/nss/doc/html/vfyserv.html @@ -1,7 +1,5 @@ -VFYSERV

    Name

    vfyserv — TBD

    Synopsis

    vfyserv

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 -

    Description

    The vfyserv tool verifies a certificate chain

    Options

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun.

    +VFYSERV

    Name

    vfyserv — TBD

    Synopsis

    vfyserv

    STATUS

    This documentation is still work in progress. Please contribute to the initial review in Mozilla NSS bug 836477 +

    Description

    The vfyserv tool verifies a certificate chain

    Options

    Additional Resources

    For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases.

    Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto

    IRC: Freenode at #dogtag-pki

    Authors

    The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google.

    Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. -

    LICENSE

    Licensed under the Mozilla Public License, version 1.1, - and/or the GNU General Public License, version 2 or later, - and/or the GNU Lesser General Public License, version 2.1 or later. +

    LICENSE

    Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

    diff --git a/security/nss/doc/nroff/certutil.1 b/security/nss/doc/nroff/certutil.1 index 1e1331d1086..3ee702b8ecc 100644 --- a/security/nss/doc/nroff/certutil.1 +++ b/security/nss/doc/nroff/certutil.1 @@ -1,13 +1,13 @@ '\" t .\" Title: CERTUTIL .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "CERTUTIL" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "CERTUTIL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -28,7 +28,7 @@ .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" -certutil \- Manage keys and certificate in the the NSS database\&. +certutil \- Manage keys and certificate in both NSS databases and other NSS tokens .SH "SYNOPSIS" .HP \w'\fBcertutil\fR\ 'u \fBcertutil\fR [\fIoptions\fR] [[\fIarguments\fR]] @@ -39,23 +39,21 @@ This documentation is still work in progress\&. Please contribute to the initial .SH "DESCRIPTION" .PP The Certificate Database Tool, -\fBcertutil\fR, is a command\-line utility that manages certs and keys in both NSS databases and other NSS tokens (such as smart cards)\&. It can specifically list, generate, modify, or delete certificates within the database, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database\&. +\fBcertutil\fR, is a command\-line utility that can create and modify certificate and key databases\&. It can specifically list, generate, modify, or delete certificates, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database\&. .PP -The key and certificate management process generally includes certificate issuance once keys and certificates have been created in the key database\&. This document discusses certificate and key database management\&. For information security module database management, see the +Certificate issuance, part of the key and certificate management process, requires that keys and certificates be created in the key database\&. This document discusses certificate and key database management\&. For information on the security module database management, see the \fBmodutil\fR manpage\&. -.SH "OPTIONS AND ARGUMENTS" +.SH "COMMAND OPTIONS AND ARGUMENTS" .PP Running \fBcertutil\fR -always requires one and only one option to specify the type of certificate operation\&. Each option may take arguments, anywhere from none to multiple arguments\&. Run the command option and +always requires one and only one command option to specify the type of certificate operation\&. Each command option may take zero or more arguments\&. The command option \fB\-H\fR -to see the arguments available for each command option\&. +will list all the command options and their relevant arguments\&. .PP \fBCommand Options\fR .PP -Command options are typically upper case\&. -.PP \-A .RS 4 Add an existing certificate to a certificate database\&. The certificate database should already exist; if one is not present, this command option will initialize one by default\&. @@ -102,12 +100,12 @@ When you delete keys, be sure to also remove any certificates associated with th .PP \-G .RS 4 -Generate a new public and private key pair within a key database\&. The key database should already exist; if one is not present, this option will initialize one by default\&. Some smart cards can store only one key pair\&. If you create a new key pair for such a card, the previous pair is overwritten\&. +Generate a new public and private key pair within a key database\&. The key database should already exist; if one is not present, this command option will initialize one by default\&. Some smart cards can store only one key pair\&. If you create a new key pair for such a card, the previous pair is overwritten\&. .RE .PP \-H .RS 4 -Display a list of the command options and arguments used by the Certificate Database Tool\&. +Display a list of the command options and arguments\&. .RE .PP \-K @@ -167,11 +165,7 @@ Change the password to a key database\&. .PP \-\-merge .RS 4 -Merge a source database into the target database\&. This is used to merge legacy NSS databases (cert8\&.db -and -key3\&.db) into the newer SQLite databases (cert9\&.db -and -key4\&.db)\&. +Merge two databases into one\&. .RE .PP \-\-upgrade\-merge @@ -223,9 +217,7 @@ supports two types of databases: the legacy security databases (cert8\&.db, key3\&.db, and secmod\&.db) and new SQLite databases (cert9\&.db, key4\&.db, and -pkcs11\&.txt)\&. If the prefix -\fBsql:\fR -is not used, then the tool assumes that the given databases are in the old format\&. +pkcs11\&.txt)\&. .sp NSS recognizes the following prefixes: .sp @@ -237,7 +229,7 @@ NSS recognizes the following prefixes: .sp -1 .IP \(bu 2.3 .\} -\fBsql: explicitly requests the newer database\fR +\fBsql: requests the newer database\fR .RE .sp .RS 4 @@ -248,19 +240,10 @@ NSS recognizes the following prefixes: .sp -1 .IP \(bu 2.3 .\} -\fBdbm: explicitly requests the older database\fR +\fBdbm: requests the legacy database\fR .RE .sp -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.sp -1 -.IP \(bu 2.3 -.\} -\fBextern: explicitly reserved for future use\fR -.RE +If no prefix is specified the default type is retrieved from NSS_DEFAULT_DB_TYPE\&. If NSS_DEFAULT_DB_TYPE is not set then dbm: is the default\&. .RE .PP \-e @@ -280,7 +263,7 @@ Set a key size to use when generating new public and private key pairs\&. The mi .PP \-h tokenname .RS 4 -Specify the name of a token to use or act on\&. Unless specified otherwise the default token is an internal slot\&. +Specify the name of a token to use or act on\&. If not specified the default token is the internal database slot\&. .RE .PP \-i input_file @@ -288,18 +271,11 @@ Specify the name of a token to use or act on\&. Unless specified otherwise the d Pass an input file to the command\&. Depending on the command option, an input file can be a specific certificate, a certificate request file, or a batch file of commands\&. .RE .PP -\-k rsa|dsa|ec|all -.RS 4 -Specify the type of a key\&. The valid options are RSA, DSA, ECC, or all\&. The default value is rsa\&. Specifying the type of key can avoid mistakes caused by duplicate nicknames\&. -.RE -.PP \-k key\-type\-or\-id .RS 4 Specify the type or specific ID of a key\&. .sp -The valid key type options are RSA, DSA, ECC, or all\&. The default value is rsa\&. Specifying the type of key can avoid mistakes caused by duplicate nicknames\&. Giving a key type generates a new key pair; giving the ID of an existing key reuses that key pair (which is required to renew certificates)\&. -.sp -The valid key type options are RSA, DSA, ECC, or all\&. The default value is rsa\&. Specifying the type of key can avoid mistakes caused by duplicate nicknames\&. Giving a key type generates a new key pair; giving the ID of an existing key reuses that key pair (which is required to renew certificates)\&. +The valid key type options are rsa, dsa, ec, or all\&. The default value is rsa\&. Specifying the type of key can avoid mistakes caused by duplicate nicknames\&. Giving a key type generates a new key pair; giving the ID of an existing key reuses that key pair (which is required to renew certificates)\&. .RE .PP \-l @@ -367,7 +343,6 @@ for each trust setting\&. In each category position, use none, any, or all of th .sp -1 .IP \(bu 2.3 .\} - \fBp\fR \- Valid peer .RE @@ -380,7 +355,6 @@ for each trust setting\&. In each category position, use none, any, or all of th .sp -1 .IP \(bu 2.3 .\} - \fBP\fR \- Trusted peer (implies p) .RE @@ -393,7 +367,6 @@ for each trust setting\&. In each category position, use none, any, or all of th .sp -1 .IP \(bu 2.3 .\} - \fBc\fR \- Valid CA .RE @@ -406,7 +379,6 @@ for each trust setting\&. In each category position, use none, any, or all of th .sp -1 .IP \(bu 2.3 .\} - \fBT\fR \- Trusted CA (implies c) .RE @@ -419,9 +391,8 @@ for each trust setting\&. In each category position, use none, any, or all of th .sp -1 .IP \(bu 2.3 .\} - \fBC\fR -\- rusted CA for client authentication (ssl server only) +\- trusted CA for client authentication (ssl server only) .RE .sp .RS 4 @@ -432,7 +403,6 @@ for each trust setting\&. In each category position, use none, any, or all of th .sp -1 .IP \(bu 2.3 .\} - \fBu\fR \- user .RE @@ -930,6 +900,21 @@ Add the Inhibit Any Policy Access extension to the certificate\&. X\&.509 certif Add the Subject Key ID extension to the certificate\&. X\&.509 certificate extensions are described in RFC 5280\&. .RE .PP +\-\-extNC +.RS 4 +Add a Name Constraint extension to the certificate\&. X\&.509 certificate extensions are described in RFC 5280\&. +.RE +.PP +\-\-keyAttrFlags attrflags +.RS 4 +PKCS #11 key Attributes\&. Comma separated list of key attribute flags, selected from the following list of choices: {token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable} +.RE +.PP +\-\-keyFlagsOn opflags, \-\-keyFlagsOff opflags +.RS 4 +PKCS #11 key Operation Flags\&. Comma separated list of one or more of the following: {token | session} {public | private} {sensitive | insensitive} {modifiable | unmodifiable} {extractable | unextractable} +.RE +.PP \-\-source\-dir certdir .RS 4 Identify the certificate database directory to upgrade\&. @@ -1035,7 +1020,6 @@ command options requires four arguments: .sp -1 .IP \(bu 2.3 .\} - \fB\-k\fR to specify either the key type to generate or, when renewing a certificate, the existing key pair to use .RE @@ -1048,7 +1032,6 @@ to specify either the key type to generate or, when renewing a certificate, the .sp -1 .IP \(bu 2.3 .\} - \fB\-g\fR to set the keysize of the key to generate .RE @@ -1061,7 +1044,6 @@ to set the keysize of the key to generate .sp -1 .IP \(bu 2.3 .\} - \fB\-s\fR to set the subject name of the certificate .RE @@ -1074,7 +1056,6 @@ to set the subject name of the certificate .sp -1 .IP \(bu 2.3 .\} - \fB\-d\fR to give the security database directory .RE @@ -1087,28 +1068,10 @@ For example: .RS 4 .\} .nf -$ certutil \-R \-k ec \-q nistb409 \-g 512 \-s "CN=John Smith,O=Example Corp,L=Mountain View,ST=California,C=US" \-d sql:/home/my/sharednssdb \-p 650\-555\-0123 \-a \-o cert\&.cer +$ certutil \-R \-k rsa \-g 1024 \-s "CN=John Smith,O=Example Corp,L=Mountain View,ST=California,C=US" \-d sql:$HOME/nssdb \-p 650\-555\-0123 \-a \-o cert\&.cer Generating key\&. This may take a few moments\&.\&.\&. - -Certificate request generated by Netscape -Phone: 650\-555\-0123 -Common Name: John Smith -Email: (not ed) -Organization: Example Corp -State: California -Country: US - -\-\-\-\-\-BEGIN NEW CERTIFICATE REQUEST\-\-\-\-\- -MIIBIDCBywIBADBmMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW -MBQGA1UEBxMNTW91bnRhaW4gVmlldzEVMBMGA1UEChMMRXhhbXBsZSBDb3JwMRMw -EQYDVQQDEwpKb2huIFNtaXRoMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMVUpDOZ -KmHnOx7reP8Cc0Lk+fFWEuYIDX9W5K/BioQOKvEjXyQZhit9aThzBVMoSf1Y1S8J -CzdUbCg1+IbnXaECAwEAAaAAMA0GCSqGSIb3DQEBBQUAA0EAryqZvpYrUtQ486Ny -qmtyQNjIi1F8c1Z+TL4uFYlMg8z6LG/J/u1E5t1QqB5e9Q4+BhRbrQjRR1JZx3tB -1hP9Gg== -\-\-\-\-\-END NEW CERTIFICATE REQUEST\-\-\-\-\- .fi .if n \{\ .RE @@ -1134,7 +1097,7 @@ $ certutil \-S \-k rsa|dsa|ec \-n certname \-s subject [\-c issuer |\-x] \-t tru .PP The series of numbers and \fB\-\-ext*\fR -options set certificate extensions that can be added to the certificate when it is generated by the CA\&. +options set certificate extensions that can be added to the certificate when it is generated by the CA\&. Interactive prompts will result\&. .PP For example, this creates a self\-signed certificate: .sp @@ -1148,6 +1111,8 @@ $ certutil \-S \-s "CN=Example CA" \-n my\-ca\-cert \-x \-t "C,C,C" \-1 \-2 \-5 .RE .\} .PP +The interative prompts for key usage and whether any extensions are critical and responses have been ommitted for brevity\&. +.PP From there, new certificates can reference the self\-signed certificate: .sp .if n \{\ @@ -1184,35 +1149,7 @@ For example: .RS 4 .\} .nf -$ certutil \-C \-c "my\-ca\-cert" \-i /home/certs/cert\&.req \-o cert\&.cer \-m 010 \-v 12 \-w 1 \-d sql:/home/my/sharednssdb \-1 nonRepudiation,dataEncipherment \-5 sslClient \-6 clientAuth \-7 jsmith@example\&.com -.fi -.if n \{\ -.RE -.\} -.PP -\fBGenerating Key Pairs\fR -.PP -Key pairs are generated automatically with a certificate request or certificate, but they can also be generated independently using the -\fB\-G\fR -command option\&. -.sp -.if n \{\ -.RS 4 -.\} -.nf -certutil \-G \-d [sql:]directory | \-h tokenname \-k key\-type \-g key\-size [\-y exponent\-value] \-q pqgfile|curve\-name -.fi -.if n \{\ -.RE -.\} -.PP -For example: -.sp -.if n \{\ -.RS 4 -.\} -.nf -$ certutil \-G \-h lunasa \-k ec \-g 256 \-q sect193r2 +$ certutil \-C \-c "my\-ca\-cert" \-i /home/certs/cert\&.req \-o cert\&.cer \-m 010 \-v 12 \-w 1 \-d sql:$HOME/nssdb \-1 nonRepudiation,dataEncipherment \-5 sslClient \-6 clientAuth \-7 jsmith@example\&.com .fi .if n \{\ .RE @@ -1254,30 +1191,94 @@ argument prints the certificate in ASCII format: .RS 4 .\} .nf -$ certutil \-L \-d sql:/home/my/sharednssdb \-a \-n "Certificate Authority \- Example Domain" - +$ certutil \-L \-d sql:$HOME/nssdb \-a \-n my\-ca\-cert \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- -MIIDmTCCAoGgAwIBAgIBATANBgkqhkiG9w0BAQUFADA5MRcwFQYDVQQKEw5FeGFt -cGxlIERvbWFpbjEeMBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEw -MDQyOTIxNTY1OFoXDTEyMDQxODIxNTY1OFowOTEXMBUGA1UEChMORXhhbXBsZSBE -b21haW4xHjAcBgNVBAMTFUNlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAO/bqUli2KwqXFKmMMG93KN1SANzNTXA/Vlf -Tmrih3hQgjvR1ktIY9aG6cB7DSKWmtHp/+p4PUCMqL4ZrSGt901qxkePyZ2dYmM2 -RnelK+SEUIPiUtoZaDhNdiYsE/yuDE8vQWj0vHCVL0w72qFUcSQ/WZT7FCrnUIUI -udeWnoPSUn70gLhcj/lvxl7K9BHyD4Sq5CzktwYtFWLiiwV+ZY/Fl6JgbGaQyQB2 -bP4iRMfloGqsxGuB1evWVDF1haGpFDSPgMnEPSLg3/3dXn+HDJbZ29EU8/xKzQEb -3V0AHKbu80zGllLEt2Zx/WDIrgJEN9yMfgKFpcmL+BvIRsmh0VsCAwEAAaOBqzCB -qDAfBgNVHSMEGDAWgBQATgxHQyRUfKIZtdp55bZlFr+tFzAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBxjAdBgNVHQ4EFgQUAE4MR0MkVHyiGbXaeeW2ZRa/ -rRcwRQYIKwYBBQUHAQEEOTA3MDUGCCsGAQUFBzABhilodHRwOi8vbG9jYWxob3N0 -LmxvY2FsZG9tYWluOjkxODAvY2Evb2NzcDANBgkqhkiG9w0BAQUFAAOCAQEAi8Gk -L3XO43u7/TDOeEsWPmq+jZsDZ3GZ85Ajt3KROLWeKVZZZa2E2Hnsvf2uXbk5amKe -lRxdSeRH9g85pv4KY7Z8xZ71NrI3+K3uwmnqkc6t0hhYb1mw/gx8OAAoluQx3biX -JBDxjI73Cf7XUopplHBjjiwyGIJUO8BEZJ5L+TF4P38MJz1snLtzZpEAX5bl0U76 -bfu/tZFWBbE8YAWYtkCtMcalBPj6jn2WD3M01kGozW4mmbvsj1cRB9HnsGsqyHCu -U0ujlL1H/RWcjn607+CTeKH9jLMUqCIqPJNOa+kq/6F7NhNRRiuzASIbZc30BZ5a -nI7q5n1USM3eWQlVXw== +MIIB1DCCAT2gAwIBAgICDkIwDQYJKoZIhvcNAQEFBQAwFTETMBEGA1UEAxMKRXhh +bXBsZSBDQTAeFw0xMzAzMTMxOTEwMjlaFw0xMzA2MTMxOTEwMjlaMBUxEzARBgNV +BAMTCkV4YW1wbGUgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ4Kzqvz +JyBVgFqDXRYSyTBNw1DrxUU/3GvWA/ngjAwHEv0Cul/6sO/gsCvnABHiH6unns6x +XRzPORlC2WY3gkk7vmlsLvYpyecNazAi/NAwVnU/66HOsaoVFWE+gBQo99UrN2yk +0BiK/GMFlLm5dXQROgA9ZKKyFdI0LIXtf6SbAgMBAAGjMzAxMBEGCWCGSAGG+EIB +AQQEAwIHADAMBgNVHRMEBTADAQH/MA4GA1UdDwEB/wQEAwICBDANBgkqhkiG9w0B +AQUFAAOBgQA6chkzkACN281d1jKMrc+RHG2UMaQyxiteaLVZO+Ro1nnRUvseDf09 +XKYFwPMJjWCihVku6bw/ihZfuMHhxK22Nue6inNQ6eDu7WmrqL8z3iUrQwxs+WiF +ob2rb8XRVVJkzXdXxlk4uo3UtNvw8sAz7sWD71qxKaIHU5q49zijfg== \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.if n \{\ +.RE +.\} +.PP +For a human\-readable display +.sp +.if n \{\ +.RS 4 +.\} +.nf +$ certutil \-L \-d sql:$HOME/nssdb \-n my\-ca\-cert +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3650 (0xe42) + Signature Algorithm: PKCS #1 SHA\-1 With RSA Encryption + Issuer: "CN=Example CA" + Validity: + Not Before: Wed Mar 13 19:10:29 2013 + Not After : Thu Jun 13 19:10:29 2013 + Subject: "CN=Example CA" + Subject Public Key Info: + Public Key Algorithm: PKCS #1 RSA Encryption + RSA Public Key: + Modulus: + 9e:0a:ce:ab:f3:27:20:55:80:5a:83:5d:16:12:c9:30: + 4d:c3:50:eb:c5:45:3f:dc:6b:d6:03:f9:e0:8c:0c:07: + 12:fd:02:ba:5f:fa:b0:ef:e0:b0:2b:e7:00:11:e2:1f: + ab:a7:9e:ce:b1:5d:1c:cf:39:19:42:d9:66:37:82:49: + 3b:be:69:6c:2e:f6:29:c9:e7:0d:6b:30:22:fc:d0:30: + 56:75:3f:eb:a1:ce:b1:aa:15:15:61:3e:80:14:28:f7: + d5:2b:37:6c:a4:d0:18:8a:fc:63:05:94:b9:b9:75:74: + 11:3a:00:3d:64:a2:b2:15:d2:34:2c:85:ed:7f:a4:9b + Exponent: 65537 (0x10001) + Signed Extensions: + Name: Certificate Type + Data: none + + Name: Certificate Basic Constraints + Data: Is a CA with no maximum path length\&. + + Name: Certificate Key Usage + Critical: True + Usages: Certificate Signing + + Signature Algorithm: PKCS #1 SHA\-1 With RSA Encryption + Signature: + 3a:72:19:33:90:00:8d:db:cd:5d:d6:32:8c:ad:cf:91: + 1c:6d:94:31:a4:32:c6:2b:5e:68:b5:59:3b:e4:68:d6: + 79:d1:52:fb:1e:0d:fd:3d:5c:a6:05:c0:f3:09:8d:60: + a2:85:59:2e:e9:bc:3f:8a:16:5f:b8:c1:e1:c4:ad:b6: + 36:e7:ba:8a:73:50:e9:e0:ee:ed:69:ab:a8:bf:33:de: + 25:2b:43:0c:6c:f9:68:85:a1:bd:ab:6f:c5:d1:55:52: + 64:cd:77:57:c6:59:38:ba:8d:d4:b4:db:f0:f2:c0:33: + ee:c5:83:ef:5a:b1:29:a2:07:53:9a:b8:f7:38:a3:7e + Fingerprint (MD5): + 86:D8:A5:8B:8A:26:BE:9E:17:A8:7B:66:10:6B:27:80 + Fingerprint (SHA1): + 48:78:09:EF:C5:D4:0C:BD:D2:64:45:59:EB:03:13:15:F7:A9:D6:F7 + + Certificate Trust Flags: + SSL Flags: + Valid CA + Trusted CA + User + Email Flags: + Valid CA + Trusted CA + User + Object Signing Flags: + Valid CA + Trusted CA + User + .fi .if n \{\ .RE @@ -1297,7 +1298,7 @@ argument to give the path to the directory\&. .RS 4 .\} .nf -$ certutil \-K \-d sql:/home/my/sharednssdb +$ certutil \-K \-d sql:$HOME/nssdb certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services " < 0> rsa 455a6673bde9375c2887ec8bf8016b3f9f35861d Thawte Freemail Member\*(Aqs Thawte Consulting (Pty) Ltd\&. ID < 1> rsa 40defeeb522ade11090eacebaaf1196a172127df Example Domain Administrator Cert @@ -1318,8 +1319,7 @@ There are ways to narrow the keys listed in the search results: .IP \(bu 2.3 .\} To return a specific key, use the -\fB\-n\fR -\fIname\fR +\fB\-n\fR\fIname\fR argument with the name of the key\&. .RE .sp @@ -1332,8 +1332,7 @@ argument with the name of the key\&. .IP \(bu 2.3 .\} If there are multiple security devices loaded, then the -\fB\-h\fR -\fItokenname\fR +\fB\-h\fR\fItokenname\fR argument can search a specific token or all tokens\&. .RE .sp @@ -1346,8 +1345,7 @@ argument can search a specific token or all tokens\&. .IP \(bu 2.3 .\} If there are multiple key types available, then the -\fB\-k\fR -\fIkey\-type\fR +\fB\-k\fR\fIkey\-type\fR argument can search a specific type of key, like RSA, DSA, or ECC\&. .RE .PP @@ -1671,7 +1669,7 @@ secmod\&.db for PKCS #11 module information .PP BerkeleyDB has performance limitations, though, which prevent it from being easily used by multiple applications simultaneously\&. NSS has some flexibility that allows applications to use their own, independent database engine while keeping a shared database and working around the access issues\&. Still, NSS requires more flexibility to provide a truly shared security database\&. .PP -In 2009, NSS introduced a new set of databases that are SQLite databases rather than BerkleyDB\&. These new databases provide more accessibility and performance: +In 2009, NSS introduced a new set of databases that are SQLite databases rather than BerkeleyDB\&. These new databases provide more accessibility and performance: .sp .RS 4 .ie n \{\ @@ -1703,7 +1701,7 @@ key4\&.db for keys .sp -1 .IP \(bu 2.3 .\} -pkcs11\&.txt, which is listing of all of the PKCS #11 modules contained in a new subdirectory in the security databases directory +pkcs11\&.txt, a listing of all of the PKCS #11 modules, contained in a new subdirectory in the security databases directory .RE .PP Because the SQLite databases are designed to be shared, these are the @@ -1845,12 +1843,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/cmsutil.1 b/security/nss/doc/nroff/cmsutil.1 index 216f4df796c..2093d6796c5 100644 --- a/security/nss/doc/nroff/cmsutil.1 +++ b/security/nss/doc/nroff/cmsutil.1 @@ -1,13 +1,13 @@ '\" t .\" Title: CMSUTIL .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "CMSUTIL" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "CMSUTIL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -77,7 +77,12 @@ Sign a message\&. .PP \fBArguments\fR .PP -Option arguments modify an action and are lowercase\&. +Option arguments modify an action\&. +.PP +\-b +.RS 4 +Decode a batch of files named in infile\&. +.RE .PP \-c content .RS 4 @@ -94,11 +99,21 @@ Specify the key/certificate database directory (default is "\&.") Specify a file containing an enveloped message for a set of recipients to which you would like to send an encrypted message\&. If this is the first encrypted message for that set of recipients, a new enveloped message will be created that you can then use for future messages (encrypt only)\&. .RE .PP +\-f pwfile +.RS 4 +Use password file to set password on all PKCS#11 tokens\&. +.RE +.PP \-G .RS 4 Include a signing time attribute (sign only)\&. .RE .PP +\-H hash +.RS 4 +Use specified hash algorithm (default:SHA1)\&. +.RE +.PP \-h num .RS 4 Generate email headers with info about CMS message (decode only)\&. @@ -109,6 +124,11 @@ Generate email headers with info about CMS message (decode only)\&. Use infile as a source of data (default is stdin)\&. .RE .PP +\-k +.RS 4 +Keep decoded encryption certs in permanent cert db\&. +.RE +.PP \-N nickname .RS 4 Specify nickname of certificate to sign with (sign only)\&. @@ -149,6 +169,11 @@ Suppress content in CMS message (sign only)\&. Set type of cert usage (default is certUsageEmailSigner)\&. .RE .PP +\-v +.RS 4 +Print debugging information\&. +.RE +.PP \-Y ekprefnick .RS 4 Specify an encryption key preference by nickname\&. @@ -237,12 +262,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/crlutil.1 b/security/nss/doc/nroff/crlutil.1 index 73041741d06..3e2c3ee32a2 100644 --- a/security/nss/doc/nroff/crlutil.1 +++ b/security/nss/doc/nroff/crlutil.1 @@ -1,13 +1,13 @@ '\" t .\" Title: CRLUTIL .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "CRLUTIL" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "CRLUTIL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -161,6 +161,16 @@ Specify type of CRL\&. possible types are: 0 \- SEC_KRL_TYPE, 1 \- SEC_CRL_TYPE\ .RS 4 Specify the url\&. .RE +.PP +\-w pwd\-string +.RS 4 +Provide db password in command line\&. +.RE +.PP +\-Z algorithm +.RS 4 +Specify the hash algorithm to use for signing the CRL\&. +.RE .SH "CRL GENERATION SCRIPT SYNTAX" .PP CRL generation script file has the following syntax: @@ -374,12 +384,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/pk12util.1 b/security/nss/doc/nroff/pk12util.1 index 28d347be701..132bdd08eed 100644 --- a/security/nss/doc/nroff/pk12util.1 +++ b/security/nss/doc/nroff/pk12util.1 @@ -1,13 +1,13 @@ '\" t .\" Title: PK12UTIL .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "PK12UTIL" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "PK12UTIL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1017,12 +1017,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/pp.1 b/security/nss/doc/nroff/pp.1 index b074f1c390e..b6fd6a5ef48 100644 --- a/security/nss/doc/nroff/pp.1 +++ b/security/nss/doc/nroff/pp.1 @@ -1,13 +1,13 @@ '\" t .\" Title: PP .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "PP" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "PP" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -63,7 +63,7 @@ Define an output file to use (default is stdout) .RE .SH "ADDITIONAL RESOURCES" .PP -NSS is maintained in conjunction with PKI and security\-related projects through Mozilla dn Fedora\&. The most closely\-related project is Dogtag PKI, with a project wiki at +NSS is maintained in conjunction with PKI and security\-related projects through Mozilla and Fedora\&. The most closely\-related project is Dogtag PKI, with a project wiki at \m[blue]\fBPKI Wiki\fR\m[]\&\s-2\u[2]\d\s+2\&. .PP For information specifically about NSS, the NSS project wiki is located at @@ -74,12 +74,12 @@ Mailing lists: pki\-devel@redhat\&.com and pki\-users@redhat\&.com IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/signtool.1 b/security/nss/doc/nroff/signtool.1 index 3a51b91da95..26e2eabe0cf 100644 --- a/security/nss/doc/nroff/signtool.1 +++ b/security/nss/doc/nroff/signtool.1 @@ -1,13 +1,13 @@ '\" t .\" Title: signtool .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "SIGNTOOL" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "SIGNTOOL" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -667,12 +667,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/signver.1 b/security/nss/doc/nroff/signver.1 index e98fe4abb9f..53c75a4d0ae 100644 --- a/security/nss/doc/nroff/signver.1 +++ b/security/nss/doc/nroff/signver.1 @@ -1,13 +1,13 @@ '\" t .\" Title: SIGNVER .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "SIGNVER" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "SIGNVER" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -306,12 +306,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/ssltap.1 b/security/nss/doc/nroff/ssltap.1 index cbe94642278..89c1c50faab 100644 --- a/security/nss/doc/nroff/ssltap.1 +++ b/security/nss/doc/nroff/ssltap.1 @@ -1,13 +1,13 @@ '\" t .\" Title: SSLTAP .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "SSLTAP" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "SSLTAP" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -590,12 +590,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/vfychain.1 b/security/nss/doc/nroff/vfychain.1 index c38293a69be..977669b0a9e 100644 --- a/security/nss/doc/nroff/vfychain.1 +++ b/security/nss/doc/nroff/vfychain.1 @@ -1,13 +1,13 @@ '\" t .\" Title: VFYCHAIN .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "VFYCHAIN" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "VFYCHAIN" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -155,12 +155,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/doc/nroff/vfyserv.1 b/security/nss/doc/nroff/vfyserv.1 index faa38023749..2dc0c0e7838 100644 --- a/security/nss/doc/nroff/vfyserv.1 +++ b/security/nss/doc/nroff/vfyserv.1 @@ -1,13 +1,13 @@ '\" t .\" Title: VFYSERV .\" Author: [see the "Authors" section] -.\" Generator: DocBook XSL Stylesheets v1.77.1 -.\" Date: 15 February 2013 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 19 July 2013 .\" Manual: NSS Security Tools .\" Source: nss-tools .\" Language: English .\" -.TH "VFYSERV" "1" "15 February 2013" "nss-tools" "NSS Security Tools" +.TH "VFYSERV" "1" "19 July 2013" "nss-tools" "NSS Security Tools" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -56,12 +56,12 @@ Mailing lists: https://lists\&.mozilla\&.org/listinfo/dev\-tech\-crypto IRC: Freenode at #dogtag\-pki .SH "AUTHORS" .PP -The NSS tools were written and maintained by developers with Netscape, Red Hat, and Sun\&. +The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google\&. .PP Authors: Elio Maldonado , Deon Lackey \&. .SH "LICENSE" .PP -Licensed under the Mozilla Public License, version 1\&.1, and/or the GNU General Public License, version 2 or later, and/or the GNU Lesser General Public License, version 2\&.1 or later\&. +Licensed under the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. .SH "NOTES" .IP " 1." 4 Mozilla NSS bug 836477 diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c index 1814d728554..c78f8ca28b4 100644 --- a/security/nss/lib/certhigh/ocsp.c +++ b/security/nss/lib/certhigh/ocsp.c @@ -3805,38 +3805,35 @@ ocsp_VerifyResponseSignature(CERTCertificate *signerCert, SECItem *tbsResponseDataDER, void *pwArg) { - SECItem rawSignature; SECKEYPublicKey *signerKey = NULL; SECStatus rv = SECFailure; + CERTSignedData signedData; /* * Now get the public key from the signer's certificate; we need * it to perform the verification. */ signerKey = CERT_ExtractPublicKey(signerCert); - if (signerKey == NULL) - return SECFailure; + if (signerKey == NULL) { + return SECFailure; + } + /* * We copy the signature data *pointer* and length, so that we can * modify the length without damaging the original copy. This is a * simple copy, not a dup, so no destroy/free is necessary. */ - rawSignature = signature->signature; - /* - * The raw signature is a bit string, but we need to represent its - * length in bytes, because that is what the verify function expects. - */ - DER_ConvertBitString(&rawSignature); + signedData.signature = signature->signature; + signedData.signatureAlgorithm = signature->signatureAlgorithm; + signedData.data = *tbsResponseDataDER; - rv = VFY_VerifyDataWithAlgorithmID(tbsResponseDataDER->data, - tbsResponseDataDER->len, - signerKey, &rawSignature, - &signature->signatureAlgorithm, - NULL, pwArg); - if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_BAD_SIGNATURE) { + rv = CERT_VerifySignedDataWithPublicKey(&signedData, signerKey, pwArg); + if (rv != SECSuccess && + (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE || + PORT_GetError() == SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED)) { PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE); } - + if (signerKey != NULL) { SECKEY_DestroyPublicKey(signerKey); } diff --git a/security/nss/lib/cryptohi/cryptohi.h b/security/nss/lib/cryptohi/cryptohi.h index 8379848e942..09297ea6a27 100644 --- a/security/nss/lib/cryptohi/cryptohi.h +++ b/security/nss/lib/cryptohi/cryptohi.h @@ -63,7 +63,7 @@ extern SGNContext *SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *privKey); /* ** Destroy a signature-context object -** "key" the object +** "cx" the object ** "freeit" if PR_TRUE then free the object as well as its sub-objects */ extern void SGN_DestroyContext(SGNContext *cx, PRBool freeit); @@ -112,7 +112,7 @@ extern SECStatus SEC_SignData(SECItem *result, ** The given signature/hash algorithm. ** "result" the final signature data (memory is allocated) ** "digest" the digest to sign -** "pk" the private key to encrypt with +** "privKey" the private key to encrypt with ** "algtag" The algorithm tag to encode (need for RSA only) */ extern SECStatus SGN_Digest(SECKEYPrivateKey *privKey, diff --git a/security/nss/lib/freebl/mpi/README b/security/nss/lib/freebl/mpi/README index 1de002a9bee..156356bcc2d 100644 --- a/security/nss/lib/freebl/mpi/README +++ b/security/nss/lib/freebl/mpi/README @@ -156,10 +156,6 @@ output parameter, without confusing anything. The basic numeric type defined by the library is an mp_int. Virtually all the functions in the library take a pointer to an mp_int as one of their parameters. An explanation of how to create and use these -
    - -

    Problem 23:

    - structures follows. And so, without further ado... diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 03f9fbb6483..27b6370b66c 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -33,12 +33,12 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define NSS_VERSION "3.15.1" _NSS_ECC_STRING _NSS_CUSTOMIZED +#define NSS_VERSION "3.15.2" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta" #define NSS_VMAJOR 3 #define NSS_VMINOR 15 -#define NSS_VPATCH 1 +#define NSS_VPATCH 2 #define NSS_VBUILD 0 -#define NSS_BETA PR_FALSE +#define NSS_BETA PR_TRUE #ifndef RC_INVOKED diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index 53b501c2466..41bdd556235 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -702,6 +702,7 @@ SECStatus PK11_CipherOp(PK11Context *context, unsigned char * out, int *outlen, SECStatus PK11_Finalize(PK11Context *context); SECStatus PK11_DigestFinal(PK11Context *context, unsigned char *data, unsigned int *outLen, unsigned int length); +#define PK11_CipherFinal PK11_DigestFinal SECStatus PK11_SaveContext(PK11Context *cx,unsigned char *save, int *len, int saveLength); diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index b540f47d4ba..744c95aa662 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -3116,6 +3116,7 @@ SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx, SECOID_CopyAlgorithmID(NULL, p12dcx->decitem.shroudAlg, &bag->safeBagContent.pkcs8ShroudedKeyBag->algorithm); } + /* fall through */ case SEC_OID_PKCS12_V1_KEY_BAG_ID: p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag); break; diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 89b5bd85e89..0591ca5db13 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -3510,6 +3510,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, case CKM_DES2_KEY_GEN: case CKM_DES3_KEY_GEN: checkWeak = PR_TRUE; + /* fall through */ case CKM_RC2_KEY_GEN: case CKM_RC4_KEY_GEN: case CKM_GENERIC_SECRET_KEY_GEN: @@ -3536,6 +3537,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, break; case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: faultyPBE3DES = PR_TRUE; + /* fall through */ case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index 4cb6d994f7f..3902324c6df 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -25,11 +25,11 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define SOFTOKEN_VERSION "3.15.1" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.15.2" SOFTOKEN_ECC_STRING " Beta" #define SOFTOKEN_VMAJOR 3 #define SOFTOKEN_VMINOR 15 -#define SOFTOKEN_VPATCH 1 +#define SOFTOKEN_VPATCH 2 #define SOFTOKEN_VBUILD 0 -#define SOFTOKEN_BETA PR_FALSE +#define SOFTOKEN_BETA PR_TRUE #endif /* _SOFTKVER_H_ */ diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h index 6f7664ac9c8..b1df773a38b 100644 --- a/security/nss/lib/ssl/ssl.h +++ b/security/nss/lib/ssl/ssl.h @@ -328,7 +328,7 @@ SSL_IMPORT SECStatus SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange); -/* Values for "policy" argument to SSL_PolicySet */ +/* Values for "policy" argument to SSL_CipherPolicySet */ /* Values returned by SSL_CipherPolicyGet. */ #define SSL_NOT_ALLOWED 0 /* or invalid or unimplemented */ #define SSL_ALLOWED 1 @@ -845,24 +845,20 @@ SSL_IMPORT SECStatus NSS_CmpCertChainWCANames(CERTCertificate *cert, SSL_IMPORT SSLKEAType NSS_FindCertKEAType(CERTCertificate * cert); /* Set cipher policies to a predefined Domestic (U.S.A.) policy. - * This essentially enables all supported ciphers. + * This essentially allows all supported ciphers. */ SSL_IMPORT SECStatus NSS_SetDomesticPolicy(void); /* Set cipher policies to a predefined Policy that is exportable from the USA * according to present U.S. policies as we understand them. - * See documentation for the list. - * Note that your particular application program may be able to obtain - * an export license with more or fewer capabilities than those allowed - * by this function. In that case, you should use SSL_SetPolicy() - * to explicitly allow those ciphers you may legally export. + * It is the same as NSS_SetDomesticPolicy now. */ SSL_IMPORT SECStatus NSS_SetExportPolicy(void); /* Set cipher policies to a predefined Policy that is exportable from the USA * according to present U.S. policies as we understand them, and that the * nation of France will permit to be imported into their country. - * See documentation for the list. + * It is the same as NSS_SetDomesticPolicy now. */ SSL_IMPORT SECStatus NSS_SetFrancePolicy(void); diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 53b6f237aec..cac55d87f09 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -67,6 +67,13 @@ static int ssl3_OIDToTLSHashAlgorithm(SECOidTag oid); static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, const unsigned char *input, int inputLen); +#ifndef NO_PKCS11_BYPASS +static SECStatus ssl3_AESGCMBypass(ssl3KeyMaterial *keys, PRBool doDecrypt, + unsigned char *out, int *outlen, int maxout, + const unsigned char *in, int inlen, + const unsigned char *additionalData, + int additionalDataLen); +#endif #define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */ #define MIN_SEND_BUF_LENGTH 4000 @@ -77,85 +84,91 @@ static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, * in this table must match the ordering in SSL_ImplementedCiphers (sslenum.c) */ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { - /* cipher_suite policy enabled is_present*/ + /* cipher_suite policy enabled isPresent */ #ifdef NSS_ENABLE_ECC - { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, + { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, #endif /* NSS_ENABLE_ECC */ - { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, -#ifdef NSS_ENABLE_ECC - { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, -#endif /* NSS_ENABLE_ECC */ - { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, + { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, #ifdef NSS_ENABLE_ECC - { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, + { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, #endif /* NSS_ENABLE_ECC */ - { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, + { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, #ifdef NSS_ENABLE_ECC - { TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, + { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, #endif /* NSS_ENABLE_ECC */ - { TLS_RSA_WITH_SEED_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { SSL_RSA_WITH_RC4_128_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, - { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, + { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, #ifdef NSS_ENABLE_ECC - { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, + { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, #endif /* NSS_ENABLE_ECC */ - { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, - { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, + { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, #ifdef NSS_ENABLE_ECC - { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, + { TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, #endif /* NSS_ENABLE_ECC */ - { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, - - - { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - - { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_RSA_WITH_SEED_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { SSL_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { SSL_RSA_WITH_RC4_128_MD5, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, #ifdef NSS_ENABLE_ECC - { TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, - { TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, #endif /* NSS_ENABLE_ECC */ - { SSL_RSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { TLS_RSA_WITH_NULL_SHA256, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { SSL_RSA_WITH_NULL_MD5, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, + { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, +#ifdef NSS_ENABLE_ECC + { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, +#endif /* NSS_ENABLE_ECC */ + { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, + + { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { SSL_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + + { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + +#ifdef NSS_ENABLE_ECC + { TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, +#endif /* NSS_ENABLE_ECC */ + { SSL_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { TLS_RSA_WITH_NULL_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, + { SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, }; /* This list of SSL3 compression methods is sorted in descending order of @@ -222,23 +235,30 @@ static SSL3Statistics ssl3stats; /* indexed by SSL3BulkCipher */ static const ssl3BulkCipherDef bulk_cipher_defs[] = { - /* cipher calg keySz secretSz type ivSz BlkSz keygen */ - {cipher_null, calg_null, 0, 0, type_stream, 0, 0, kg_null}, - {cipher_rc4, calg_rc4, 16, 16, type_stream, 0, 0, kg_strong}, - {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, kg_export}, - {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, kg_export}, - {cipher_rc2, calg_rc2, 16, 16, type_block, 8, 8, kg_strong}, - {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, kg_export}, - {cipher_des, calg_des, 8, 8, type_block, 8, 8, kg_strong}, - {cipher_3des, calg_3des, 24, 24, type_block, 8, 8, kg_strong}, - {cipher_des40, calg_des, 8, 5, type_block, 8, 8, kg_export}, - {cipher_idea, calg_idea, 16, 16, type_block, 8, 8, kg_strong}, - {cipher_aes_128, calg_aes, 16, 16, type_block, 16,16, kg_strong}, - {cipher_aes_256, calg_aes, 32, 32, type_block, 16,16, kg_strong}, - {cipher_camellia_128, calg_camellia,16, 16, type_block, 16,16, kg_strong}, - {cipher_camellia_256, calg_camellia,32, 32, type_block, 16,16, kg_strong}, - {cipher_seed, calg_seed, 16, 16, type_block, 16,16, kg_strong}, - {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, kg_null}, + /* |--------- Lengths --------| */ + /* cipher calg k s type i b t n */ + /* e e v l a o */ + /* y c | o g n */ + /* | r | c | c */ + /* | e | k | e */ + /* | t | | | | */ + {cipher_null, calg_null, 0, 0, type_stream, 0, 0, 0, 0}, + {cipher_rc4, calg_rc4, 16,16, type_stream, 0, 0, 0, 0}, + {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, 0, 0}, + {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, 0, 0}, + {cipher_rc2, calg_rc2, 16,16, type_block, 8, 8, 0, 0}, + {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, 0, 0}, + {cipher_des, calg_des, 8, 8, type_block, 8, 8, 0, 0}, + {cipher_3des, calg_3des, 24,24, type_block, 8, 8, 0, 0}, + {cipher_des40, calg_des, 8, 5, type_block, 8, 8, 0, 0}, + {cipher_idea, calg_idea, 16,16, type_block, 8, 8, 0, 0}, + {cipher_aes_128, calg_aes, 16,16, type_block, 16,16, 0, 0}, + {cipher_aes_256, calg_aes, 32,32, type_block, 16,16, 0, 0}, + {cipher_camellia_128, calg_camellia, 16,16, type_block, 16,16, 0, 0}, + {cipher_camellia_256, calg_camellia, 32,32, type_block, 16,16, 0, 0}, + {cipher_seed, calg_seed, 16,16, type_block, 16,16, 0, 0}, + {cipher_aes_128_gcm, calg_aes_gcm, 16,16, type_aead, 4, 0,16, 8}, + {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0}, }; static const ssl3KEADef kea_defs[] = @@ -360,6 +380,11 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] = {SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_rsa_fips}, {SSL_RSA_FIPS_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_rsa_fips}, + {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_rsa}, + {TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_rsa}, + {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_rsa}, + {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_ecdsa}, + #ifdef NSS_ENABLE_ECC {TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_ecdsa}, {TLS_ECDH_ECDSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_ecdsa}, @@ -423,10 +448,11 @@ static const SSLCipher2Mech alg2Mech[] = { { calg_aes , CKM_AES_CBC }, { calg_camellia , CKM_CAMELLIA_CBC }, { calg_seed , CKM_SEED_CBC }, + { calg_aes_gcm , CKM_AES_GCM }, /* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */ }; -#define mmech_null (CK_MECHANISM_TYPE)0x80000000L +#define mmech_invalid (CK_MECHANISM_TYPE)0x80000000L #define mmech_md5 CKM_SSL3_MD5_MAC #define mmech_sha CKM_SSL3_SHA1_MAC #define mmech_md5_hmac CKM_MD5_HMAC @@ -436,12 +462,13 @@ static const SSLCipher2Mech alg2Mech[] = { static const ssl3MACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */ /* pad_size is only used for SSL 3.0 MAC. See RFC 6101 Sec. 5.2.3.1. */ /* mac mmech pad_size mac_size */ - { mac_null, mmech_null, 0, 0 }, + { mac_null, mmech_invalid, 0, 0 }, { mac_md5, mmech_md5, 48, MD5_LENGTH }, { mac_sha, mmech_sha, 40, SHA1_LENGTH}, {hmac_md5, mmech_md5_hmac, 0, MD5_LENGTH }, {hmac_sha, mmech_sha_hmac, 0, SHA1_LENGTH}, {hmac_sha256, mmech_sha256_hmac, 0, SHA256_LENGTH}, + { mac_aead, mmech_invalid, 0, 0 }, }; /* indexed by SSL3BulkCipher */ @@ -461,6 +488,7 @@ const char * const ssl3_cipherName[] = { "Camellia-128", "Camellia-256", "SEED-CBC", + "AES-128-GCM", "missing" }; @@ -587,9 +615,13 @@ ssl3_CipherSuiteAllowedForVersion(ssl3CipherSuite cipherSuite, case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: case TLS_RSA_WITH_AES_256_CBC_SHA256: case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: case TLS_RSA_WITH_AES_128_CBC_SHA256: + case TLS_RSA_WITH_AES_128_GCM_SHA256: case TLS_RSA_WITH_NULL_SHA256: return version >= SSL_LIBRARY_VERSION_TLS_1_2; default: @@ -761,7 +793,7 @@ count_cipher_suites(sslSocket *ss, int policy, PRBool enabled) int i, count = 0; if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { - return 0; + return 0; } for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { if (config_match(&ss->cipherSuites[i], policy, enabled)) @@ -1349,7 +1381,7 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss) cipher = suite_def->bulk_cipher_alg; kea = suite_def->key_exchange_alg; mac = suite_def->mac_alg; - if (mac <= ssl_mac_sha && isTLS) + if (mac <= ssl_mac_sha && mac != ssl_mac_null && isTLS) mac += 2; ss->ssl3.hs.suite_def = suite_def; @@ -1543,7 +1575,6 @@ ssl3_InitPendingContextsBypass(sslSocket *ss) unsigned int optArg2 = 0; PRBool server_encrypts = ss->sec.isServer; SSLCipherAlgorithm calg; - SSLCompressionMethod compression_method; SECStatus rv; PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); @@ -1554,7 +1585,17 @@ ssl3_InitPendingContextsBypass(sslSocket *ss) cipher_def = pwSpec->cipher_def; calg = cipher_def->calg; - compression_method = pwSpec->compression_method; + + if (calg == calg_aes_gcm) { + pwSpec->encode = NULL; + pwSpec->decode = NULL; + pwSpec->destroy = NULL; + pwSpec->encodeContext = NULL; + pwSpec->decodeContext = NULL; + pwSpec->aead = ssl3_AESGCMBypass; + ssl3_InitCompressionContext(pwSpec); + return SECSuccess; + } serverContext = pwSpec->server.cipher_context; clientContext = pwSpec->client.cipher_context; @@ -1710,6 +1751,195 @@ ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits) return param; } +/* ssl3_BuildRecordPseudoHeader writes the SSL/TLS pseudo-header (the data + * which is included in the MAC or AEAD additional data) to |out| and returns + * its length. See https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the + * definition of the AEAD additional data. + * + * TLS pseudo-header includes the record's version field, SSL's doesn't. Which + * pseudo-header defintiion to use should be decided based on the version of + * the protocol that was negotiated when the cipher spec became current, NOT + * based on the version value in the record itself, and the decision is passed + * to this function as the |includesVersion| argument. But, the |version| + * argument should be the record's version value. + */ +static unsigned int +ssl3_BuildRecordPseudoHeader(unsigned char *out, + SSL3SequenceNumber seq_num, + SSL3ContentType type, + PRBool includesVersion, + SSL3ProtocolVersion version, + PRBool isDTLS, + int length) +{ + out[0] = (unsigned char)(seq_num.high >> 24); + out[1] = (unsigned char)(seq_num.high >> 16); + out[2] = (unsigned char)(seq_num.high >> 8); + out[3] = (unsigned char)(seq_num.high >> 0); + out[4] = (unsigned char)(seq_num.low >> 24); + out[5] = (unsigned char)(seq_num.low >> 16); + out[6] = (unsigned char)(seq_num.low >> 8); + out[7] = (unsigned char)(seq_num.low >> 0); + out[8] = type; + + /* SSL3 MAC doesn't include the record's version field. */ + if (!includesVersion) { + out[9] = MSB(length); + out[10] = LSB(length); + return 11; + } + + /* TLS MAC and AEAD additional data include version. */ + if (isDTLS) { + SSL3ProtocolVersion dtls_version; + + dtls_version = dtls_TLSVersionToDTLSVersion(version); + out[9] = MSB(dtls_version); + out[10] = LSB(dtls_version); + } else { + out[9] = MSB(version); + out[10] = LSB(version); + } + out[11] = MSB(length); + out[12] = LSB(length); + return 13; +} + +static SECStatus +ssl3_AESGCM(ssl3KeyMaterial *keys, + PRBool doDecrypt, + unsigned char *out, + int *outlen, + int maxout, + const unsigned char *in, + int inlen, + const unsigned char *additionalData, + int additionalDataLen) +{ + SECItem param; + SECStatus rv = SECFailure; + unsigned char nonce[12]; + unsigned int uOutLen; + CK_GCM_PARAMS gcmParams; + + static const int tagSize = 16; + static const int explicitNonceLen = 8; + + /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the + * nonce is formed. */ + memcpy(nonce, keys->write_iv, 4); + if (doDecrypt) { + memcpy(nonce + 4, in, explicitNonceLen); + in += explicitNonceLen; + inlen -= explicitNonceLen; + *outlen = 0; + } else { + if (maxout < explicitNonceLen) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + /* Use the 64-bit sequence number as the explicit nonce. */ + memcpy(nonce + 4, additionalData, explicitNonceLen); + memcpy(out, additionalData, explicitNonceLen); + out += explicitNonceLen; + maxout -= explicitNonceLen; + *outlen = explicitNonceLen; + } + + param.type = siBuffer; + param.data = (unsigned char *) &gcmParams; + param.len = sizeof(gcmParams); + gcmParams.pIv = nonce; + gcmParams.ulIvLen = sizeof(nonce); + gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */ + gcmParams.ulAADLen = additionalDataLen; + gcmParams.ulTagBits = tagSize * 8; + + if (doDecrypt) { + rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, + maxout, in, inlen); + } else { + rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, + maxout, in, inlen); + } + *outlen += (int) uOutLen; + + return rv; +} + +#ifndef NO_PKCS11_BYPASS +static SECStatus +ssl3_AESGCMBypass(ssl3KeyMaterial *keys, + PRBool doDecrypt, + unsigned char *out, + int *outlen, + int maxout, + const unsigned char *in, + int inlen, + const unsigned char *additionalData, + int additionalDataLen) +{ + SECStatus rv = SECFailure; + unsigned char nonce[12]; + unsigned int uOutLen; + AESContext *cx; + CK_GCM_PARAMS gcmParams; + + static const int tagSize = 16; + static const int explicitNonceLen = 8; + + /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the + * nonce is formed. */ + PORT_Assert(keys->write_iv_item.len == 4); + if (keys->write_iv_item.len != 4) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + memcpy(nonce, keys->write_iv_item.data, 4); + if (doDecrypt) { + memcpy(nonce + 4, in, explicitNonceLen); + in += explicitNonceLen; + inlen -= explicitNonceLen; + *outlen = 0; + } else { + if (maxout < explicitNonceLen) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + /* Use the 64-bit sequence number as the explicit nonce. */ + memcpy(nonce + 4, additionalData, explicitNonceLen); + memcpy(out, additionalData, explicitNonceLen); + out += explicitNonceLen; + maxout -= explicitNonceLen; + *outlen = explicitNonceLen; + } + + gcmParams.pIv = nonce; + gcmParams.ulIvLen = sizeof(nonce); + gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */ + gcmParams.ulAADLen = additionalDataLen; + gcmParams.ulTagBits = tagSize * 8; + + cx = (AESContext *)keys->cipher_context; + rv = AES_InitContext(cx, keys->write_key_item.data, + keys->write_key_item.len, + (unsigned char *)&gcmParams, NSS_AES_GCM, !doDecrypt, + AES_BLOCK_SIZE); + if (rv != SECSuccess) { + return rv; + } + if (doDecrypt) { + rv = AES_Decrypt(cx, out, &uOutLen, maxout, in, inlen); + } else { + rv = AES_Encrypt(cx, out, &uOutLen, maxout, in, inlen); + } + AES_DestroyContext(cx, PR_FALSE); + *outlen += (int) uOutLen; + + return rv; +} +#endif + /* Initialize encryption and MAC contexts for pending spec. * Master Secret already is derived. * Caller holds Spec write lock. @@ -1737,14 +1967,27 @@ ssl3_InitPendingContextsPKCS11(sslSocket *ss) pwSpec = ss->ssl3.pwSpec; cipher_def = pwSpec->cipher_def; macLength = pwSpec->mac_size; + calg = cipher_def->calg; + PORT_Assert(alg2Mech[calg].calg == calg); + + pwSpec->client.write_mac_context = NULL; + pwSpec->server.write_mac_context = NULL; + + if (calg == calg_aes_gcm) { + pwSpec->encode = NULL; + pwSpec->decode = NULL; + pwSpec->destroy = NULL; + pwSpec->encodeContext = NULL; + pwSpec->decodeContext = NULL; + pwSpec->aead = ssl3_AESGCM; + return SECSuccess; + } /* ** Now setup the MAC contexts, ** crypto contexts are setup below. */ - pwSpec->client.write_mac_context = NULL; - pwSpec->server.write_mac_context = NULL; mac_mech = pwSpec->mac_def->mmech; mac_param.data = (unsigned char *)&macLength; mac_param.len = sizeof(macLength); @@ -1767,9 +2010,6 @@ ssl3_InitPendingContextsPKCS11(sslSocket *ss) ** Now setup the crypto contexts. */ - calg = cipher_def->calg; - PORT_Assert(alg2Mech[calg].calg == calg); - if (calg == calg_null) { pwSpec->encode = Null_Cipher; pwSpec->decode = Null_Cipher; @@ -1977,10 +2217,8 @@ static SECStatus ssl3_ComputeRecordMAC( ssl3CipherSpec * spec, PRBool useServerMacKey, - PRBool isDTLS, - SSL3ContentType type, - SSL3ProtocolVersion version, - SSL3SequenceNumber seq_num, + const unsigned char *header, + unsigned int headerLen, const SSL3Opaque * input, int inputLength, unsigned char * outbuf, @@ -1988,56 +2226,8 @@ ssl3_ComputeRecordMAC( { const ssl3MACDef * mac_def; SECStatus rv; -#ifndef NO_PKCS11_BYPASS - PRBool isTLS; -#endif - unsigned int tempLen; - unsigned char temp[MAX_MAC_LENGTH]; - temp[0] = (unsigned char)(seq_num.high >> 24); - temp[1] = (unsigned char)(seq_num.high >> 16); - temp[2] = (unsigned char)(seq_num.high >> 8); - temp[3] = (unsigned char)(seq_num.high >> 0); - temp[4] = (unsigned char)(seq_num.low >> 24); - temp[5] = (unsigned char)(seq_num.low >> 16); - temp[6] = (unsigned char)(seq_num.low >> 8); - temp[7] = (unsigned char)(seq_num.low >> 0); - temp[8] = type; - - /* TLS MAC includes the record's version field, SSL's doesn't. - ** We decide which MAC defintiion to use based on the version of - ** the protocol that was negotiated when the spec became current, - ** NOT based on the version value in the record itself. - ** But, we use the record'v version value in the computation. - */ - if (spec->version <= SSL_LIBRARY_VERSION_3_0) { - temp[9] = MSB(inputLength); - temp[10] = LSB(inputLength); - tempLen = 11; -#ifndef NO_PKCS11_BYPASS - isTLS = PR_FALSE; -#endif - } else { - /* New TLS hash includes version. */ - if (isDTLS) { - SSL3ProtocolVersion dtls_version; - - dtls_version = dtls_TLSVersionToDTLSVersion(version); - temp[9] = MSB(dtls_version); - temp[10] = LSB(dtls_version); - } else { - temp[9] = MSB(version); - temp[10] = LSB(version); - } - temp[11] = MSB(inputLength); - temp[12] = LSB(inputLength); - tempLen = 13; -#ifndef NO_PKCS11_BYPASS - isTLS = PR_TRUE; -#endif - } - - PRINT_BUF(95, (NULL, "frag hash1: temp", temp, tempLen)); + PRINT_BUF(95, (NULL, "frag hash1: header", header, headerLen)); PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength)); mac_def = spec->mac_def; @@ -2082,7 +2272,10 @@ ssl3_ComputeRecordMAC( return SECFailure; } - if (!isTLS) { + if (spec->version <= SSL_LIBRARY_VERSION_3_0) { + unsigned int tempLen; + unsigned char temp[MAX_MAC_LENGTH]; + /* compute "inner" part of SSL3 MAC */ hashObj->begin(write_mac_context); if (useServerMacKey) @@ -2094,7 +2287,7 @@ ssl3_ComputeRecordMAC( spec->client.write_mac_key_item.data, spec->client.write_mac_key_item.len); hashObj->update(write_mac_context, mac_pad_1, pad_bytes); - hashObj->update(write_mac_context, temp, tempLen); + hashObj->update(write_mac_context, header, headerLen); hashObj->update(write_mac_context, input, inputLength); hashObj->end(write_mac_context, temp, &tempLen, sizeof temp); @@ -2125,7 +2318,7 @@ ssl3_ComputeRecordMAC( } if (rv == SECSuccess) { HMAC_Begin(cx); - HMAC_Update(cx, temp, tempLen); + HMAC_Update(cx, header, headerLen); HMAC_Update(cx, input, inputLength); rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size); HMAC_Destroy(cx, PR_FALSE); @@ -2139,7 +2332,7 @@ ssl3_ComputeRecordMAC( (useServerMacKey ? spec->server.write_mac_context : spec->client.write_mac_context); rv = PK11_DigestBegin(mac_context); - rv |= PK11_DigestOp(mac_context, temp, tempLen); + rv |= PK11_DigestOp(mac_context, header, headerLen); rv |= PK11_DigestOp(mac_context, input, inputLength); rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size); } @@ -2165,10 +2358,8 @@ static SECStatus ssl3_ComputeRecordMACConstantTime( ssl3CipherSpec * spec, PRBool useServerMacKey, - PRBool isDTLS, - SSL3ContentType type, - SSL3ProtocolVersion version, - SSL3SequenceNumber seq_num, + const unsigned char *header, + unsigned int headerLen, const SSL3Opaque * input, int inputLen, int originalLen, @@ -2179,9 +2370,7 @@ ssl3_ComputeRecordMACConstantTime( CK_NSS_MAC_CONSTANT_TIME_PARAMS params; SECItem param, inputItem, outputItem; SECStatus rv; - unsigned char header[13]; PK11SymKey * key; - int recordLength; PORT_Assert(inputLen >= spec->mac_size); PORT_Assert(originalLen >= inputLen); @@ -2197,42 +2386,15 @@ ssl3_ComputeRecordMACConstantTime( return SECSuccess; } - header[0] = (unsigned char)(seq_num.high >> 24); - header[1] = (unsigned char)(seq_num.high >> 16); - header[2] = (unsigned char)(seq_num.high >> 8); - header[3] = (unsigned char)(seq_num.high >> 0); - header[4] = (unsigned char)(seq_num.low >> 24); - header[5] = (unsigned char)(seq_num.low >> 16); - header[6] = (unsigned char)(seq_num.low >> 8); - header[7] = (unsigned char)(seq_num.low >> 0); - header[8] = type; - macType = CKM_NSS_HMAC_CONSTANT_TIME; - recordLength = inputLen - spec->mac_size; if (spec->version <= SSL_LIBRARY_VERSION_3_0) { macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME; - header[9] = recordLength >> 8; - header[10] = recordLength; - params.ulHeaderLen = 11; - } else { - if (isDTLS) { - SSL3ProtocolVersion dtls_version; - - dtls_version = dtls_TLSVersionToDTLSVersion(version); - header[9] = dtls_version >> 8; - header[10] = dtls_version; - } else { - header[9] = version >> 8; - header[10] = version; - } - header[11] = recordLength >> 8; - header[12] = recordLength; - params.ulHeaderLen = 13; } params.macAlg = spec->mac_def->mmech; params.ulBodyTotalLen = originalLen; - params.pHeader = header; + params.pHeader = (unsigned char *) header; /* const cast */ + params.ulHeaderLen = headerLen; param.data = (unsigned char*) ¶ms; param.len = sizeof(params); @@ -2272,9 +2434,8 @@ fallback: /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the * length already. */ inputLen -= spec->mac_size; - return ssl3_ComputeRecordMAC(spec, useServerMacKey, isDTLS, type, - version, seq_num, input, inputLen, - outbuf, outLen); + return ssl3_ComputeRecordMAC(spec, useServerMacKey, header, headerLen, + input, inputLen, outbuf, outLen); } static PRBool @@ -2323,6 +2484,8 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, PRUint16 headerLen; int ivLen = 0; int cipherBytes = 0; + unsigned char pseudoHeader[13]; + unsigned int pseudoHeaderLen; cipher_def = cwSpec->cipher_def; headerLen = isDTLS ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH; @@ -2368,86 +2531,117 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, contentLen = outlen; } - /* - * Add the MAC - */ - rv = ssl3_ComputeRecordMAC( cwSpec, isServer, isDTLS, - type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen, - wrBuf->buf + headerLen + ivLen + contentLen, &macLen); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); - return SECFailure; - } - p1Len = contentLen; - p2Len = macLen; - fragLen = contentLen + macLen; /* needs to be encrypted */ - PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024); + pseudoHeaderLen = ssl3_BuildRecordPseudoHeader( + pseudoHeader, cwSpec->write_seq_num, type, + cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version, + isDTLS, contentLen); + PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader)); + if (cipher_def->type == type_aead) { + const int nonceLen = cipher_def->explicit_nonce_size; + const int tagLen = cipher_def->tag_size; - /* - * Pad the text (if we're doing a block cipher) - * then Encrypt it - */ - if (cipher_def->type == type_block) { - unsigned char * pBuf; - int padding_length; - int i; - - oddLen = contentLen % cipher_def->block_size; - /* Assume blockSize is a power of two */ - padding_length = cipher_def->block_size - 1 - - ((fragLen) & (cipher_def->block_size - 1)); - fragLen += padding_length + 1; - PORT_Assert((fragLen % cipher_def->block_size) == 0); - - /* Pad according to TLS rules (also acceptable to SSL3). */ - pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1]; - for (i = padding_length + 1; i > 0; --i) { - *pBuf-- = padding_length; + if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + cipherBytes = contentLen; + rv = cwSpec->aead( + isServer ? &cwSpec->server : &cwSpec->client, + PR_FALSE, /* do encrypt */ + wrBuf->buf + headerLen, /* output */ + &cipherBytes, /* out len */ + wrBuf->space - headerLen, /* max out */ + pIn, contentLen, /* input */ + pseudoHeader, pseudoHeaderLen); + if (rv != SECSuccess) { + PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); + return SECFailure; } - /* now, if contentLen is not a multiple of block size, fix it */ - p2Len = fragLen - p1Len; - } - if (p1Len < 256) { - oddLen = p1Len; - p1Len = 0; } else { - p1Len -= oddLen; - } - if (oddLen) { - p2Len += oddLen; - PORT_Assert( (cipher_def->block_size < 2) || \ - (p2Len % cipher_def->block_size) == 0); - memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len, oddLen); - } - if (p1Len > 0) { - int cipherBytesPart1 = -1; - rv = cwSpec->encode( cwSpec->encodeContext, - wrBuf->buf + headerLen + ivLen, /* output */ - &cipherBytesPart1, /* actual outlen */ - p1Len, /* max outlen */ - pIn, p1Len); /* input, and inputlen */ - PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len); - if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) { - PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); + /* + * Add the MAC + */ + rv = ssl3_ComputeRecordMAC(cwSpec, isServer, + pseudoHeader, pseudoHeaderLen, pIn, contentLen, + wrBuf->buf + headerLen + ivLen + contentLen, &macLen); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); return SECFailure; } - cipherBytes += cipherBytesPart1; - } - if (p2Len > 0) { - int cipherBytesPart2 = -1; - rv = cwSpec->encode( cwSpec->encodeContext, - wrBuf->buf + headerLen + ivLen + p1Len, - &cipherBytesPart2, /* output and actual outLen */ - p2Len, /* max outlen */ - wrBuf->buf + headerLen + ivLen + p1Len, - p2Len); /* input and inputLen*/ - PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len); - if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) { - PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); - return SECFailure; + p1Len = contentLen; + p2Len = macLen; + fragLen = contentLen + macLen; /* needs to be encrypted */ + PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024); + + /* + * Pad the text (if we're doing a block cipher) + * then Encrypt it + */ + if (cipher_def->type == type_block) { + unsigned char * pBuf; + int padding_length; + int i; + + oddLen = contentLen % cipher_def->block_size; + /* Assume blockSize is a power of two */ + padding_length = cipher_def->block_size - 1 - + ((fragLen) & (cipher_def->block_size - 1)); + fragLen += padding_length + 1; + PORT_Assert((fragLen % cipher_def->block_size) == 0); + + /* Pad according to TLS rules (also acceptable to SSL3). */ + pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1]; + for (i = padding_length + 1; i > 0; --i) { + *pBuf-- = padding_length; + } + /* now, if contentLen is not a multiple of block size, fix it */ + p2Len = fragLen - p1Len; } - cipherBytes += cipherBytesPart2; - } + if (p1Len < 256) { + oddLen = p1Len; + p1Len = 0; + } else { + p1Len -= oddLen; + } + if (oddLen) { + p2Len += oddLen; + PORT_Assert( (cipher_def->block_size < 2) || \ + (p2Len % cipher_def->block_size) == 0); + memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len, + oddLen); + } + if (p1Len > 0) { + int cipherBytesPart1 = -1; + rv = cwSpec->encode( cwSpec->encodeContext, + wrBuf->buf + headerLen + ivLen, /* output */ + &cipherBytesPart1, /* actual outlen */ + p1Len, /* max outlen */ + pIn, p1Len); /* input, and inputlen */ + PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len); + if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) { + PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); + return SECFailure; + } + cipherBytes += cipherBytesPart1; + } + if (p2Len > 0) { + int cipherBytesPart2 = -1; + rv = cwSpec->encode( cwSpec->encodeContext, + wrBuf->buf + headerLen + ivLen + p1Len, + &cipherBytesPart2, /* output and actual outLen */ + p2Len, /* max outlen */ + wrBuf->buf + headerLen + ivLen + p1Len, + p2Len); /* input and inputLen*/ + PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len); + if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) { + PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); + return SECFailure; + } + cipherBytes += cipherBytesPart2; + } + } + PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024); wrBuf->len = cipherBytes + headerLen; @@ -2990,9 +3184,6 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc) static SECStatus ssl3_IllegalParameter(sslSocket *ss) { - PRBool isTLS; - - isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT : SSL_ERROR_BAD_SERVER ); @@ -3516,7 +3707,6 @@ ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss) } key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited); - /* was: (CK_BBOOL)(cipher_def->keygen_mode != kg_strong); */ key_material_params.RandomInfo.pClientRandom = cr; key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; @@ -7455,7 +7645,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto alert_loser; suite_found: - /* Look for a matching compression algorithm. */ + /* Select a compression algorithm. */ for (i = 0; i < comps.len; i++) { if (!compressionEnabled(ss, comps.data[i])) continue; @@ -9707,7 +9897,6 @@ ssl3_SendNextProto(sslSocket *ss) static void ssl3_RecordKeyLog(sslSocket *ss) { - sslSessionID *sid; SECStatus rv; SECItem *keyData; char buf[14 /* "CLIENT_RANDOM " */ + @@ -9719,8 +9908,6 @@ ssl3_RecordKeyLog(sslSocket *ss) PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - sid = ss->sec.ci.sid; - if (!ssl_keylog_iob) return; @@ -10539,7 +10726,7 @@ ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext, /* SSLv3 padding bytes are random and cannot be checked. */ t = plaintext->len; t -= paddingLength+overhead; - /* If len >= padding_length+overhead then the MSB of t is zero. */ + /* If len >= paddingLength+overhead then the MSB of t is zero. */ good = DUPLICATE_MSB_TO_ALL(~t); /* SSLv3 requires that the padding is minimal. */ t = blockSize - (paddingLength+1); @@ -10705,6 +10892,8 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) unsigned int originalLen = 0; unsigned int good; unsigned int minLength; + unsigned char header[13]; + unsigned int headerLen; PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); @@ -10772,7 +10961,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) } } - good = (unsigned)-1; + good = ~0U; minLength = crSpec->mac_size; if (cipher_def->type == type_block) { /* CBC records have a padding length byte at the end. */ @@ -10781,19 +10970,14 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) /* With >= TLS 1.1, CBC records have an explicit IV. */ minLength += cipher_def->iv_size; } + } else if (cipher_def->type == type_aead) { + minLength = cipher_def->explicit_nonce_size + cipher_def->tag_size; } /* We can perform this test in variable time because the record's total * length and the ciphersuite are both public knowledge. */ if (cText->buf->len < minLength) { - SSL_DBG(("%d: SSL3[%d]: HandleRecord, record too small.", - SSL_GETPID(), ss->fd)); - /* must not hold spec lock when calling SSL3_SendAlert. */ - ssl_ReleaseSpecReadLock(ss); - SSL3_SendAlert(ss, alert_fatal, bad_record_mac); - /* always log mac error, in case attacker can read server logs. */ - PORT_SetError(SSL_ERROR_BAD_MAC_READ); - return SECFailure; + goto decrypt_loser; } if (cipher_def->type == type_block && @@ -10861,78 +11045,112 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) return SECFailure; } - /* decrypt from cText buf to plaintext. */ - rv = crSpec->decode( - crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len, - plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); - good &= SECStatusToMask(rv); + rType = cText->type; + if (cipher_def->type == type_aead) { + /* XXX For many AEAD ciphers, the plaintext is shorter than the + * ciphertext by a fixed byte count, but it is not true in general. + * Each AEAD cipher should provide a function that returns the + * plaintext length for a given ciphertext. */ + unsigned int decryptedLen = + cText->buf->len - cipher_def->explicit_nonce_size - + cipher_def->tag_size; + headerLen = ssl3_BuildRecordPseudoHeader( + header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, + rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen); + PORT_Assert(headerLen <= sizeof(header)); + rv = crSpec->aead( + ss->sec.isServer ? &crSpec->client : &crSpec->server, + PR_TRUE, /* do decrypt */ + plaintext->buf, /* out */ + (int*) &plaintext->len, /* outlen */ + plaintext->space, /* maxout */ + cText->buf->buf, /* in */ + cText->buf->len, /* inlen */ + header, headerLen); + if (rv != SECSuccess) { + good = 0; + } + } else { + if (cipher_def->type == type_block && + ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) { + goto decrypt_loser; + } - PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len)); + /* decrypt from cText buf to plaintext. */ + rv = crSpec->decode( + crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len, + plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); + if (rv != SECSuccess) { + goto decrypt_loser; + } - originalLen = plaintext->len; + PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len)); - /* If it's a block cipher, check and strip the padding. */ - if (cipher_def->type == type_block) { - const unsigned int blockSize = cipher_def->iv_size; - const unsigned int macSize = crSpec->mac_size; + originalLen = plaintext->len; - if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) { - good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding( - plaintext, blockSize, macSize)); + /* If it's a block cipher, check and strip the padding. */ + if (cipher_def->type == type_block) { + const unsigned int blockSize = cipher_def->block_size; + const unsigned int macSize = crSpec->mac_size; + + if (!isTLS) { + good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding( + plaintext, blockSize, macSize)); + } else { + good &= SECStatusToMask(ssl_RemoveTLSCBCPadding( + plaintext, macSize)); + } + } + + /* compute the MAC */ + headerLen = ssl3_BuildRecordPseudoHeader( + header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, + rType, isTLS, cText->version, IS_DTLS(ss), + plaintext->len - crSpec->mac_size); + PORT_Assert(headerLen <= sizeof(header)); + if (cipher_def->type == type_block) { + rv = ssl3_ComputeRecordMACConstantTime( + crSpec, (PRBool)(!ss->sec.isServer), header, headerLen, + plaintext->buf, plaintext->len, originalLen, + hash, &hashBytes); + + ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf, + crSpec->mac_size); + givenHash = givenHashBuf; + + /* plaintext->len will always have enough space to remove the MAC + * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust + * plaintext->len if the result has enough space for the MAC and we + * tested the unadjusted size against minLength, above. */ + plaintext->len -= crSpec->mac_size; } else { - good &= SECStatusToMask(ssl_RemoveTLSCBCPadding( - plaintext, macSize)); + /* This is safe because we checked the minLength above. */ + plaintext->len -= crSpec->mac_size; + + rv = ssl3_ComputeRecordMAC( + crSpec, (PRBool)(!ss->sec.isServer), header, headerLen, + plaintext->buf, plaintext->len, hash, &hashBytes); + + /* We can read the MAC directly from the record because its location + * is public when a stream cipher is used. */ + givenHash = plaintext->buf + plaintext->len; + } + + good &= SECStatusToMask(rv); + + if (hashBytes != (unsigned)crSpec->mac_size || + NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) { + /* We're allowed to leak whether or not the MAC check was correct */ + good = 0; } } - /* compute the MAC */ - rType = cText->type; - if (cipher_def->type == type_block) { - rv = ssl3_ComputeRecordMACConstantTime( - crSpec, (PRBool)(!ss->sec.isServer), - IS_DTLS(ss), rType, cText->version, - IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, - plaintext->buf, plaintext->len, originalLen, - hash, &hashBytes); - - ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf, - crSpec->mac_size); - givenHash = givenHashBuf; - - /* plaintext->len will always have enough space to remove the MAC - * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust - * plaintext->len if the result has enough space for the MAC and we - * tested the unadjusted size against minLength, above. */ - plaintext->len -= crSpec->mac_size; - } else { - /* This is safe because we checked the minLength above. */ - plaintext->len -= crSpec->mac_size; - - rv = ssl3_ComputeRecordMAC( - crSpec, (PRBool)(!ss->sec.isServer), - IS_DTLS(ss), rType, cText->version, - IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, - plaintext->buf, plaintext->len, - hash, &hashBytes); - - /* We can read the MAC directly from the record because its location is - * public when a stream cipher is used. */ - givenHash = plaintext->buf + plaintext->len; - } - - good &= SECStatusToMask(rv); - - if (hashBytes != (unsigned)crSpec->mac_size || - NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) { - /* We're allowed to leak whether or not the MAC check was correct */ - good = 0; - } - if (good == 0) { +decrypt_loser: /* must not hold spec lock when calling SSL3_SendAlert. */ ssl_ReleaseSpecReadLock(ss); - SSL_DBG(("%d: SSL3[%d]: mac check failed", SSL_GETPID(), ss->fd)); + SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd)); if (!IS_DTLS(ss)) { SSL3_SendAlert(ss, alert_fatal, bad_record_mac); diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c index 65a428f9fe2..6380cfe3c85 100644 --- a/security/nss/lib/ssl/ssl3ecc.c +++ b/security/nss/lib/ssl/ssl3ecc.c @@ -896,6 +896,7 @@ static const ssl3CipherSuite ecdhe_ecdsa_suites[] = { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, @@ -906,6 +907,7 @@ static const ssl3CipherSuite ecdhe_rsa_suites[] = { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, @@ -917,12 +919,14 @@ static const ssl3CipherSuite ecSuites[] = { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, diff --git a/security/nss/lib/ssl/ssl3ext.c b/security/nss/lib/ssl/ssl3ext.c index f6e9e2b787c..616ca4c6fd1 100644 --- a/security/nss/lib/ssl/ssl3ext.c +++ b/security/nss/lib/ssl/ssl3ext.c @@ -1411,7 +1411,7 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, goto no_ticket; /* Allow for the wrapped master secret to be longer. */ - if (buffer_len < sizeof(SSL3_MASTER_SECRET_LENGTH)) + if (buffer_len < parsed_session_ticket->ms_length) goto no_ticket; PORT_Memcpy(parsed_session_ticket->master_secret, buffer, parsed_session_ticket->ms_length); diff --git a/security/nss/lib/ssl/sslcon.c b/security/nss/lib/ssl/sslcon.c index 2fc6602a2b6..bd0ffb8c87c 100644 --- a/security/nss/lib/ssl/sslcon.c +++ b/security/nss/lib/ssl/sslcon.c @@ -20,7 +20,6 @@ #include "prinit.h" #include "prtime.h" /* for PR_Now() */ -#define XXX static PRBool policyWasSet; /* This ordered list is indexed by (SSL_CK_xx * 3) */ diff --git a/security/nss/lib/ssl/sslenum.c b/security/nss/lib/ssl/sslenum.c index b460f2631dc..597ec072399 100644 --- a/security/nss/lib/ssl/sslenum.c +++ b/security/nss/lib/ssl/sslenum.c @@ -29,6 +29,14 @@ * Finally, update the ssl_V3_SUITES_IMPLEMENTED macro in sslimpl.h. */ const PRUint16 SSL_ImplementedCiphers[] = { + /* AES-GCM */ +#ifdef NSS_ENABLE_ECC + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, +#endif /* NSS_ENABLE_ECC */ + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_128_GCM_SHA256, + /* 256-bit */ #ifdef NSS_ENABLE_ECC TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index b3e36e67e7d..32616750d4a 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -54,6 +54,7 @@ typedef SSLSignType SSL3SignType; #define calg_aes ssl_calg_aes #define calg_camellia ssl_calg_camellia #define calg_seed ssl_calg_seed +#define calg_aes_gcm ssl_calg_aes_gcm #define mac_null ssl_mac_null #define mac_md5 ssl_mac_md5 @@ -61,6 +62,7 @@ typedef SSLSignType SSL3SignType; #define hmac_md5 ssl_hmac_md5 #define hmac_sha ssl_hmac_sha #define hmac_sha256 ssl_hmac_sha256 +#define mac_aead ssl_mac_aead #define SET_ERROR_CODE /* reminder */ #define SEND_ALERT /* reminder */ @@ -280,9 +282,9 @@ typedef struct { } ssl3CipherSuiteCfg; #ifdef NSS_ENABLE_ECC -#define ssl_V3_SUITES_IMPLEMENTED 57 +#define ssl_V3_SUITES_IMPLEMENTED 61 #else -#define ssl_V3_SUITES_IMPLEMENTED 35 +#define ssl_V3_SUITES_IMPLEMENTED 37 #endif /* NSS_ENABLE_ECC */ #define MAX_DTLS_SRTP_CIPHER_SUITES 4 @@ -430,20 +432,6 @@ struct sslGatherStr { #define GS_DATA 3 #define GS_PAD 4 -typedef SECStatus (*SSLCipher)(void * context, - unsigned char * out, - int * outlen, - int maxout, - const unsigned char *in, - int inlen); -typedef SECStatus (*SSLCompressor)(void * context, - unsigned char * out, - int * outlen, - int maxout, - const unsigned char *in, - int inlen); -typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit); - /* @@ -467,11 +455,12 @@ typedef enum { cipher_camellia_128, cipher_camellia_256, cipher_seed, + cipher_aes_128_gcm, cipher_missing /* reserved for no such supported cipher */ /* This enum must match ssl3_cipherName[] in ssl3con.c. */ } SSL3BulkCipher; -typedef enum { type_stream, type_block } CipherType; +typedef enum { type_stream, type_block, type_aead } CipherType; #define MAX_IV_LENGTH 24 @@ -513,6 +502,30 @@ typedef struct { PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS]; } ssl3KeyMaterial; +typedef SECStatus (*SSLCipher)(void * context, + unsigned char * out, + int * outlen, + int maxout, + const unsigned char *in, + int inlen); +typedef SECStatus (*SSLAEADCipher)( + ssl3KeyMaterial * keys, + PRBool doDecrypt, + unsigned char * out, + int * outlen, + int maxout, + const unsigned char *in, + int inlen, + const unsigned char *additionalData, + int additionalDataLen); +typedef SECStatus (*SSLCompressor)(void * context, + unsigned char * out, + int * outlen, + int maxout, + const unsigned char *in, + int inlen); +typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit); + /* The DTLS anti-replay window. Defined here because we need it in * the cipher spec. Note that this is a ring buffer but left and * right represent the true window, with modular arithmetic used to @@ -539,6 +552,7 @@ typedef struct { int mac_size; SSLCipher encode; SSLCipher decode; + SSLAEADCipher aead; SSLDestroy destroy; void * encodeContext; void * decodeContext; @@ -685,8 +699,6 @@ typedef struct { PRBool tls_keygen; } ssl3KEADef; -typedef enum { kg_null, kg_strong, kg_export } SSL3KeyGenMode; - /* ** There are tables of these, all const. */ @@ -698,7 +710,8 @@ struct ssl3BulkCipherDefStr { CipherType type; int iv_size; int block_size; - SSL3KeyGenMode keygen_mode; + int tag_size; /* authentication tag size for AEAD ciphers. */ + int explicit_nonce_size; /* for AEAD ciphers. */ }; /* @@ -1737,7 +1750,7 @@ extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd); extern void ssl_FreePRSocket(PRFileDesc *fd); -/* Internal config function so SSL2 can initialize the present state of +/* Internal config function so SSL3 can initialize the present state of * various ciphers */ extern int ssl3_config_match_init(sslSocket *); diff --git a/security/nss/lib/ssl/sslinfo.c b/security/nss/lib/ssl/sslinfo.c index d0c23b73382..89545e0c8c1 100644 --- a/security/nss/lib/ssl/sslinfo.c +++ b/security/nss/lib/ssl/sslinfo.c @@ -101,7 +101,7 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) #define K_ECDHE "ECDHE", kt_ecdh #define C_SEED "SEED", calg_seed -#define C_CAMELLIA "CAMELLIA", calg_camellia +#define C_CAMELLIA "CAMELLIA", calg_camellia #define C_AES "AES", calg_aes #define C_RC4 "RC4", calg_rc4 #define C_RC2 "RC2", calg_rc2 @@ -109,6 +109,7 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) #define C_3DES "3DES", calg_3des #define C_NULL "NULL", calg_null #define C_SJ "SKIPJACK", calg_sj +#define C_AESGCM "AES-GCM", calg_aes_gcm #define B_256 256, 256, 256 #define B_128 128, 128, 128 @@ -119,12 +120,16 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) #define B_40 128, 40, 40 #define B_0 0, 0, 0 +#define M_AEAD_128 "AEAD", ssl_mac_aead, 128 #define M_SHA256 "SHA256", ssl_hmac_sha256, 256 #define M_SHA "SHA1", ssl_mac_sha, 160 #define M_MD5 "MD5", ssl_mac_md5, 128 +#define M_NULL "NULL", ssl_mac_null, 0 static const SSLCipherSuiteInfo suiteInfo[] = { /* <------ Cipher suite --------------------> */ +{0,CS(TLS_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, }, + {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, }, {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, }, {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0, }, @@ -138,6 +143,7 @@ static const SSLCipherSuiteInfo suiteInfo[] = { {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, }, {0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0, }, {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0, }, +{0,CS(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, }, {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, }, {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, }, {0,CS(TLS_RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0, }, @@ -167,6 +173,9 @@ static const SSLCipherSuiteInfo suiteInfo[] = { #ifdef NSS_ENABLE_ECC /* ECC cipher suites */ +{0,CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, }, +{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0, }, + {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, }, {0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, }, {0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, }, diff --git a/security/nss/lib/ssl/sslproto.h b/security/nss/lib/ssl/sslproto.h index b037887acf9..53bba011bb9 100644 --- a/security/nss/lib/ssl/sslproto.h +++ b/security/nss/lib/ssl/sslproto.h @@ -162,6 +162,10 @@ #define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E +#define TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2 + /* TLS "Signaling Cipher Suite Value" (SCSV). May be requested by client. * Must NEVER be chosen by server. SSL 3.0 server acknowledges by sending * back an empty Renegotiation Info (RI) server hello extension. @@ -204,6 +208,11 @@ #define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 + /* Netscape "experimental" cipher suites. */ #define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0 #define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1 diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 488b7f2a0a9..4424221f852 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -21,88 +21,6 @@ #define SET_ERROR_CODE /* reminder */ -struct cipherPolicyStr { - int cipher; - unsigned char export; /* policy value for export policy */ - unsigned char france; /* policy value for france policy */ -}; - -typedef struct cipherPolicyStr cipherPolicy; - -/* This table contains two preconfigured policies: Export and France. -** It is used only by the functions NSS_SetDomesticPolicy, -** NSS_SetExportPolicy, and NSS_SetFrancePolicy. -** Order of entries is not important. -*/ -static cipherPolicy ssl_ciphers[] = { /* Export France */ - { SSL_EN_RC4_128_WITH_MD5, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_ALLOWED, SSL_ALLOWED }, - { SSL_EN_RC2_128_CBC_WITH_MD5, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_ALLOWED, SSL_ALLOWED }, - { SSL_EN_DES_64_CBC_WITH_MD5, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_RSA_WITH_RC4_128_MD5, SSL_RESTRICTED, SSL_NOT_ALLOWED }, - { SSL_RSA_WITH_RC4_128_SHA, SSL_RESTRICTED, SSL_NOT_ALLOWED }, - { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RESTRICTED, SSL_NOT_ALLOWED }, - { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED, SSL_ALLOWED }, - { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_ALLOWED, SSL_ALLOWED }, - { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED, SSL_ALLOWED }, - { SSL_RSA_WITH_NULL_SHA, SSL_ALLOWED, SSL_ALLOWED }, - { TLS_RSA_WITH_NULL_SHA256, SSL_ALLOWED, SSL_ALLOWED }, - { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_WITH_SEED_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_ALLOWED, SSL_NOT_ALLOWED }, -#ifdef NSS_ENABLE_ECC - { TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, SSL_ALLOWED }, - { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, SSL_ALLOWED }, - { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_ALLOWED, SSL_ALLOWED }, - { TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_ALLOWED, SSL_ALLOWED }, - { TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, -#endif /* NSS_ENABLE_ECC */ - { 0, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED } -}; - static const sslSocketOps ssl_default_ops = { /* No SSL. */ ssl_DefConnect, NULL, @@ -1338,10 +1256,10 @@ SECStatus NSS_SetDomesticPolicy(void) { SECStatus status = SECSuccess; - cipherPolicy * policy; + const PRUint16 *cipher; - for (policy = ssl_ciphers; policy->cipher != 0; ++policy) { - status = SSL_SetPolicy(policy->cipher, SSL_ALLOWED); + for (cipher = SSL_ImplementedCiphers; *cipher != 0; ++cipher) { + status = SSL_SetPolicy(*cipher, SSL_ALLOWED); if (status != SECSuccess) break; } @@ -2951,6 +2869,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) ss->opt.useSocks = PR_FALSE; ss->opt.noLocks = !makeLocks; ss->vrange = *VERSIONS_DEFAULTS(protocolVariant); + ss->protocolVariant = protocolVariant; ss->peerID = NULL; ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; @@ -3004,7 +2923,6 @@ loser: PORT_Free(ss); ss = NULL; } - ss->protocolVariant = protocolVariant; } return ss; } diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h index 613983f31d5..6b93629340e 100644 --- a/security/nss/lib/ssl/sslt.h +++ b/security/nss/lib/ssl/sslt.h @@ -78,9 +78,10 @@ typedef enum { ssl_calg_3des = 4, ssl_calg_idea = 5, ssl_calg_fortezza = 6, /* deprecated, now unused */ - ssl_calg_aes = 7, /* coming soon */ + ssl_calg_aes = 7, ssl_calg_camellia = 8, - ssl_calg_seed = 9 + ssl_calg_seed = 9, + ssl_calg_aes_gcm = 10 } SSLCipherAlgorithm; typedef enum { @@ -89,7 +90,8 @@ typedef enum { ssl_mac_sha = 2, ssl_hmac_md5 = 3, /* TLS HMAC version of mac_md5 */ ssl_hmac_sha = 4, /* TLS HMAC version of mac_sha */ - ssl_hmac_sha256 = 5 + ssl_hmac_sha256 = 5, + ssl_mac_aead = 6 } SSLMACAlgorithm; typedef enum { @@ -145,6 +147,9 @@ typedef struct SSLCipherSuiteInfoStr { PRUint16 effectiveKeyBits; /* MAC info */ + /* AEAD ciphers don't have a MAC. For an AEAD cipher, macAlgorithmName + * is "AEAD", macAlgorithm is ssl_mac_aead, and macBits is the length in + * bits of the authentication tag. */ const char * macAlgorithmName; SSLMACAlgorithm macAlgorithm; PRUint16 macBits; diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index cb150bfa526..8e9bd2a79c7 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,12 +19,12 @@ * The format of the version string should be * ".[.[.]][ ]" */ -#define NSSUTIL_VERSION "3.15.1" +#define NSSUTIL_VERSION "3.15.2 Beta" #define NSSUTIL_VMAJOR 3 #define NSSUTIL_VMINOR 15 -#define NSSUTIL_VPATCH 1 +#define NSSUTIL_VPATCH 2 #define NSSUTIL_VBUILD 0 -#define NSSUTIL_BETA PR_FALSE +#define NSSUTIL_BETA PR_TRUE SEC_BEGIN_PROTOS diff --git a/security/nss/lib/util/utilpars.c b/security/nss/lib/util/utilpars.c index cbf777ff1a5..d2cd3e04ae7 100644 --- a/security/nss/lib/util/utilpars.c +++ b/security/nss/lib/util/utilpars.c @@ -677,7 +677,7 @@ nssutil_mkSlotFlags(unsigned long defaultFlags) int i,j; for (i=0; i < sizeof(defaultFlags)*8; i++) { - if (defaultFlags & (1< Date: Sat, 24 Aug 2013 01:33:46 +0200 Subject: [PATCH 32/87] Bug 899052 - Implement the listAddons request; r=fitzgen --- browser/devtools/debugger/test/Makefile.in | 3 + .../debugger/test/browser_dbg_addon1.xpi | Bin 0 -> 71453 bytes .../debugger/test/browser_dbg_addon2.xpi | Bin 0 -> 71455 bytes .../debugger/test/browser_dbg_listaddons.js | 100 ++++++++++++++++++ browser/devtools/debugger/test/head.js | 30 ++++++ toolkit/components/telemetry/Histograms.json | 12 +++ toolkit/devtools/client/dbg-client.jsm | 17 ++- toolkit/devtools/server/actors/root.js | 45 +++++++- toolkit/devtools/server/actors/webbrowser.js | 91 +++++++++++++++- .../devtools/server/tests/unit/testactors.js | 2 +- 10 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 browser/devtools/debugger/test/browser_dbg_addon1.xpi create mode 100644 browser/devtools/debugger/test/browser_dbg_addon2.xpi create mode 100644 browser/devtools/debugger/test/browser_dbg_listaddons.js diff --git a/browser/devtools/debugger/test/Makefile.in b/browser/devtools/debugger/test/Makefile.in index 1420aed37d6..bf122e9b223 100644 --- a/browser/devtools/debugger/test/Makefile.in +++ b/browser/devtools/debugger/test/Makefile.in @@ -24,6 +24,7 @@ MOCHITEST_BROWSER_TESTS = \ browser_dbg_cmd_blackbox.js \ browser_dbg_cmd_break.js \ browser_dbg_debuggerstatement.js \ + browser_dbg_listaddons.js \ browser_dbg_listtabs-01.js \ browser_dbg_listtabs-02.js \ browser_dbg_tabactor-01.js \ @@ -130,6 +131,8 @@ MOCHITEST_BROWSER_PAGES = \ testactors.js \ browser_dbg_tab1.html \ browser_dbg_tab2.html \ + browser_dbg_addon1.xpi \ + browser_dbg_addon2.xpi \ browser_dbg_debuggerstatement.html \ browser_dbg_stack.html \ browser_dbg_script-switching.html \ diff --git a/browser/devtools/debugger/test/browser_dbg_addon1.xpi b/browser/devtools/debugger/test/browser_dbg_addon1.xpi new file mode 100644 index 0000000000000000000000000000000000000000..b77ec953125d620c5746638272be32d1bc341a90 GIT binary patch literal 71453 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�@X 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

    By9c2iZI z2y%K};nSbV4f_n~ePt=^a(2zJ34&s{?YQJOahGy$fcEuG7=``|*o;q&W`@b~qUi*uh~BVjS8D!ni~ ziyi{EfIJ(2kS|FPlc8$J8OHPriw82IhPt}Cj?lK{vL+@66*u&BJhg2U6Kxk0R+r}? zT;$kLWHKwPbdnCWG^*Z^Rlh~K(`Gq%xv--6t6q_WV10=VaA8XG4WkB3#2rZUfD}yw z3Up^mPotLFa?`x7?zK_OzRbbe6!q5z6g8ID2V+xCsY%9mKH0<;B8DI=ZJePvi0i}4 zw3cz65Hg2L2aKKWOZ|^&`T-!kF?G^%8#BHqVfObi6AH8|hMIse$z#qOMKjQa6EgNG zR{=lgGHW7T+%z;X28FW5z=-M2Av^GceeW#$gr`tmm|KEgwHjgE9%F=OCtl9=CZumE z>@I83Grhf?T|Xb&-b^)1*w91j)0I0*g zcV9r+Kf4l4Um5D3UcA^`KveDO9YJ=Ae}YZ}CuSs17~V!1vl4-*iF5Q`5CJiXtR)^k{ zDjcI!1)?4C;GTBAR`NU@_I)y6=nq&W(Wp?hDM`hW`F1J`X<)9zl-Sa#VAR; zXC=g%&BM&b1oGo{S$Hm(rk922i7Jo=rHSz_fGB<@BsgW}m-Q*y?vYCfyWlfAS&dNZ zh8>Wy`s!pDGK(9T?l~V(k-7DIe+ZZ_qMxHg?*A1vve)O2u|a_I2JKF;b>cvd*d$GB zjvj&y$Uq6}`}FF~X=X?MS(C?rMnBD`kHBavIZB)L7k0Pn<2 zX6DtPve;o?+^p3l2K`n&&zYo?{|d`!y1{u;5aLrYZqYWvJXhK zCNu@3UfxyfjBd3{<0n$YmEOTtYG};Z|GDXreVru!5mH^I=1uLN;qm9Ws2G$ku0d~b z%#$A6AVsyYk38CVj&^Twbs+Uw+sy5=kdDIaRCD9U~+S{dYkchIwvO;9Bww;OK>&jB6v6C6Q%C5QcGAS1l3x3udI-T#4lF6l9eP^PzB3VvlS+xZTiv)-hv-3?Fgy-{RsK z(l<=JNM}9d$%7(M;qYT3^Z)*I(NwacYqe=I-W)R4`Q0}Z?tpuZzGr!V6eUmp{vh%HF!qjZf_2N5Xxg@I+gWLwm9}lG z(zb2eth8<0w$-`MZrr<{r~5rWV9if!#*7#-z-9BxQJTwzfQ_r&n{9LACG`9Mp>iYm zhyKCF*y%sIj}`!N_QW3uy%FZ01tS0Y+S%b>OVBRWb(?)Q1n=eFFb@W#i;^NaP}rg! zuvi5AYjk@Dc@$_2v{8n1By*%?Zrc6dTbS|j^b%`MvrGI$8R_qtY5jLdSHI`_q+N>z zTjyB&n%HP((k{_*Y8`%{EmVJ@d5syV?|t&m5GyP|{B{xI3J|(oRn=0OqZ{QO_Q7S) z4H^OdqUCjg<9=GJz#nL9VUCL!J*yv!ZLUh3UxTe75q9-O#Z?{>)MGcWFhmdmPIank z*mxCeJBTfYbd_dQQ@zJHjl|p(amDU%P9nas{R)dl!zmw4wg<%plHVdrZA7%)nkyKE zuV!`xEeTmB{X(K*Zj5WCS0zR1)uO&2;kExD?$Ly`}O-Vv;-*cCF@M7{%tQ3AB{8R|ejd&5pvayfGouR#;2&CL~x( ztO&Z2{&ZL@r!0kJD+h*2WM^g*Xa@;^a;gCjL3+-Tf|PWeG+1wHB%6(TB~(uW0flLb z@=9i=>n`n=X4a9SP_Vl#T|DdewHG|2OnN_N%^I*SqoHQXmg6G{Ks`C%B)df@rcMl& zRi|VfXdvTB#~!vJ2FYD&0^|oiT!E(oMrAHM+&<(ieF3_Tq1*Ea77aN9v_>1qD zzrwck3$IG=7g7#`lht(BoTe!r>Qwti3M){lY%@7A%pq76Rzh3=*yz`1SyxIRov|N z9?$97io9@n?hP!C-p+bFUh5%+{UsqJ8TdR`fY?}3n{f;1z1Ns8o%Y`w-_-Kg3R{YC zpjCD3{U6cNOk|j&APea7V}-qHIm}2$h}+o_GxswaX>iA!Ys7iZMEkqFP#$1=fE{_% zH#%>2UT_2@r}8D0Vb?TsK#)~Xm9 zuECwe3$Lvsk32;1(d2uu%yvlqkd5$8oMu@CoOI7W!Eu^9A5a{+ZOsqwzECzDqT$vY zsj{zBW49$B^}vS06L5)d(`_6lpo&CIX1Oy?<0Ej&pUXHuv}s)@71lKa7bcgBvm(sh z^6V$G_z%ec`&dT$4^{Ce6v)ZM*1`HeO5>kiXOPLCvdH=4L-9}U(f|7hH#z@kQ zq;BcB&W85+bX)ZUS`8OJ_P7M*3!9@XViA9HFV7#c{zf|7?+Xk9ewyX|;e zOw+OspTSlo4uJk_f7OPr_m$eEE-_iHvYqUoRVrD_yjYF7b?Wn#K*7C4xl{#mF5Iys zO*_#Ke^yXwIYsyGPCJh1IiWME$fAK$pAq><=ow#k54vBeoMElz_!_?HFp0HTCwW$# zbpIC_wIgX03b~Ms5n5ens9R-Pa*KiWx^>_itJiH1jN)4tVpntv< zDz!e<+3eeTrOT(-$H}hWiaD9xtq!)kh@pY`564DXpIzvePo2FZ{wW3yL=B=jIc`B0 z<;gAc!kar)rh2*R0rl)yG(GsxV^`(V zwGc6jW8yKI{!2;&rXp-RAu0h8TAT|31;f&`Q5=@NTj!~wWPP1z=W>-G%#5*0mL08E5CTKK+j=~$d(9S z_lH&47{l}i5voCJSE`gz12&#y$d_}GFGN`6%du(nMmECzO$+cyf!JjI*WXP?Qc|fY z?Xm69aupFgQKacs6t_ZyQD@o-1{M<)SeBtl@Td$>pyqyDw&6$?4X}tYwr|pb&P5AF z3MR2-9F5qQbaZ-{sDJBG)#~)SsYn2mul`v-OJ9`q*82=zn)}j^0z+5Mf2KJyzAkF>3(!>K9mHk8kK3D7>ks0RKT(zLEN3i4imOiO=ta4dM-cLA1So zGgLODGIKv97DCm=DKYAUCp%RnVb)5+vAwt9~UnF z+^Jj7_kBt)m;DhZfm=j-kX4#_3=wkxpC3vOW-jK@u>j@1n&+^QzhhKWvz?=(t*zDN z>wWw6@t84R(O^nmGEB@qnf`?=1zN9uc1i~WGe9&B zVjq|*-Wg{By^weA)1W{Lhz3Mex8n^vQ$u0^uKxwfRF1BL2S{L;k_?YCm3Ps9!{Y6C zDhxrRBdzx;WFh}z56~Qmz9h$NTaS>=-wE{8WriQvn zjEm_7LAVZpM8b2HkTCczTjfqJrL(+#$`F>ngXy@?VHWg4LB>~azcv-in^ z*PlB|->32y z8n9jQJw%b<$~E2rG-iK#XW(rl2l@n6!KvYJ&g( z2-G}Sb~i;OM{I`#yGz9y7S0Mg>q}o_wQ|4PJTie7ZX=Gqp1}HOxCY`dV2O3b+UN>) zC)toxeYEnevp!GLD}H1>6^b3EM_+w_3yN$p8wzm&0N@g}K9iWGilj|FG1!D8a~5ZM zDMf9qx7N1!g8ncG8Y=+@42`mOg{B822@$M`>dXtbolVgiOy1Pxo|fvcZcG982OP5~ ztDasWWNVlbbrhkCm>Cm#qe@`8p>01qi>#j6h`izyl;&gTAR>dR!a859g*O>WN< zott<|L=I;s)E#8knm637k6e`Tm(NcbMqUX>hc6{m@+A{)UvqJ$D>@yjV1H zH}~796bwwS3*TP^lkg4VPY>i;7889FH)BujO3UB{UHr}4 zP9BJ}y&C|;YWgN0L-u>C<0-#O=ySR_yWPCKzIozSdCBKDsma$CaoHw(rMB|Ab0B`S z75dXxW;$RgJ;YCc&mO8#nn!%jizmRwvUs_DAD_-xt_(V@QQMDEA0$P$0is8pglBHD z9IQ|`>DMW9uB_v6LmSU2!AdfCwd>PNuJSKH7iyYD2gnB20GfCPSZl0@jTdEf5zuM_#GMigB*OSid~jcC2BIMB zie`IYSg!+}Cr&-w;CzZia4i8JlT2`lD<-8tpL&cQkkttW70+pl;(OZ02iY~m@#kZ~ zsm*T~dGnxg40pu#oZqSL~h zV%G-FqSOd&^|@t#S}wUbzsOjvIT6ZXf1sJ36wE5h;S_d!c;c!Vh$=1HpLZ{k%sM|4 z(otGz&wM(R%5(f1C+758;&@)D(ozjS2ffi-0)Ficu*+a19bb4`6yxM(D8)E9BNv9- zyP%ykYzyQO@$B?afM&rnc|vB2gl^=xs*F4j4e}Z=9y8<314}j#>5iR&jHmHOTTz_Z zP*)>1mq_hA`iYw(8fshY&JV^Pwm`q)k=h17HKS2e?uWYYDxb0MnrY?MQeQrEoE(9U z&a7#sC(`}Y6jk3~YuT(2f5mmu*-r&Bg8%aQ2_KYB{O1HX7r#XFMzM*5mFRv_0eGCg z`rdSU8kXGY$t2o_|2^4e#mDhhO2J1S=CQRP1E{@u@hTUbu*Ls0>CEzeQ!o0;dOVQD z;J7c-zm#CPN%-)D!Nlg_WJ53oehW!|+Tch}ETo#)QM5Sh%c)6^NYmt2vK`aarEd08 zJV41WIvy}{14AGRSZ)dd*>nCBKFLLnwh|%qH*6v>uosGqN13>?zya?hMUai3*f#3` zyg4|d`9|)fL3-5#^y=Rum%q3Zbk(cBFLroGNIRKA1VBdU@Be;nlak0uB`MalRgN$FaZp;G$d_@+3Zbxm6a5#adp`mh&vT9tG)$?Q?5dj%U0 zDQeihh5HiSr2w>wxMS4+{+qB9=}F8DCfp}Dn`gcUH(H>;i^uDb5l4{$mrypo>Dfds znqw3A0-Ms*CQfA48t4|fYq;?@-~Ue|IreHvro__&{y#R^&u{G?B%r;hMj^ zX8HWl(!7Pk@^N>Q%F$GhPdnjvye?X~Z8`3f6VXXS+v`@EmuN{%)=y{Xhy_zlcAsZ{ z=cKDpqn%$%{5d1^Dtf4|a$1p)RU#9i0x;*Z+0mzAb2WQV4;W+iPU&9Tz-t%%v3Qz& z*>U4Mn$>AANaZPCxZ9xCfu!&gU+%+ek4)xs8;h2chHUU15X!sM?k+VAK5yp(m10o*M{c z&MeJQ4w-l4UXhso}eN@9MaYMl7ENBa5y}VxYgaKjQT3_ zjC~#BS@~h=ges?xI)i(;;ZbWEmr^KZ>@6+3L9IGaoadVbIjY^XLr8UKZVil2PW9#| zr=em@+WB75De3g(?dx_#Lm2Jy=^F<7gy|<*Rgu2)Kj%l8k5=e6*oRg`d36#m`h|pS zxnhga$b$KR0+hJaRuG@}<`^JX5nlF!d$T6gX zYR2UrOuAUaI4Qa^nHHaDC5E;{8<1liwr(A*5YH3NuTpAe<4qg3?gMMK%rzsG0SZKh zx~j51BRu|qagUxdC0dve-iN55a~3Rut$2W;PzkHn7ICoSXpkwos6uKe_vY>B?(%*0 za?PYrowH#%}S5?H8P?x9F>SN^x{9#8q zx9u(Ud_6=00ERU6#H3eJbX}gcRq$D^kbtP1E6UCh+ou@nl;%$1eyFzb(RT#5nKB=L z*xF==Fk5bv@0tHxiRm1i4u#j5L2+A4)0#@hW49<|iF%ev40Sn!{QL=Y+u-ZRX zo|7mbIDHq6Cam+O3oheomF?)9>sl9OSq8NaK@c6QXPYwI4H;!vx|E^@fx6d)Fon3E zy*cPEp@$!(d9#0DGM?7o2&MoF*bC@yF+Iph{ut?9YP^uz$4;1a{!w+!^>PLD;!c$oUbWl*>e(-JW+Um=gpdH=$e8>j}iqD zi+aJebP}pj9eYw966#e%c}4xj=~0Fe`$R;fZ6L01l1KQkd6L<$v2B)n?z-_23XiG1 z$bC^}?^ZgjZ7AY%ae<=V1&R7sV4C46y>_1xa2gQv2n!71oDjC?0#)=Ue0lYKJR`%E z{n|HE=gYy{-QM%HI1RI3sklJejp}Y8-?TeRTMe!^B?Knt_GDEFn!y@UWy|Lvie4tM zzYS=Z)UC%4*}InO9*8r`)~ia%Mh#-aCfCc<$VZj%?iBP_TrDU%Xffxnbtz3NuQEk2 zEf-806sncQbm8e`3{6r;f!o1BnQc)Ib3aya&c^(uuq7j@kzeu%jIbp9TLx|3HV_&R zm)>>hzfaV`Q1c25q0jL~M&~B-KanRyZDu&o7v6kU{U}l9W|t8AIYBpsWR8P!tX?u< z3bD{N&@=;bys#L^kGK}uXs8E2=aQUVOXs@6%{S z+l1TPOZx>XrA$6|oYx9%>aUrcS!!En=kVt~l0E7_RHN&*Wy>D04g6qNux_+fIls&8 zDh0dsT{E%=rO=wL2cN^}OoyVI=v@VXCQ=@{LUe?-%#kPJ@2p`=D4Y%k`V-hG?RT=> zt5~yYC)oi-yp!t8R6o0A5=7px=*%%@_~p(+j~R0w$lz@;%;MOi!If5a7sK!9@knS! za`+)pQ$zE7tW1?fbn=oCym#DLE7}v*to{6qWWTw@c$KymyOBO9Cak2jhj%`Wr^jXO z0GMa<7cGZRVa>~?%2eRu=|7_7-uC;xJ7eGfVPdup^NGgmXeG%&@Jyb zL%X|;^OBy{D>$pWUqz*jUZ$l*%a8;-&dAP_VLhACoxYnjVW;B^osT*wW2Uk3kcezmu#8(z-pfIW5Wmi&|Zvh)Ou83 zSurVw8H&mw_ER8ZrC?1?i}G_sWAT=@*!NkgI#&8tR3uX=MWjG8i)INpK!zqi^^ioG zCISz&PKG*f@XCoIoxBd<>03@`yL{cj*^EC6v46_c_36tqaM!n zH3=hrsd+;=!&L!x{uP|qeNsRvq8tro@SQ4YVZU+ztby^GsdPrB#A>r)0m;1ku=AyIF7m|a_+~i&W;KvLcTOqU*el@mzYbeHf%*7 zX@YZ_Ihtf-3|fT;%oL-F<{`pFj9XWq3{jYzA9O5*_(Snt;uaXp9UHWM+fQZsJy_^l zSXrMC(Oj;sx$!(+z-B7O>&wmo;jaVV0m)nvrjDcBxC7`F>oRfApN=l*C7xFL%V_L6 zYU11AcB+%RL6{36&*@LcI#U=XC7xiivE6D0e(+v%mV<)EfT^?^07)66r9bGz#qbPu z(4ZShk`9d+k&FjxoGif8tdE;AAA5_1(B!MZ`QuB7)V?+MVk*gCjog$H|mAHCiGGdyx=jUo{3jn**;_iZj z(Dd_YK9po4l$oFYx)|$QA@RN?siUoW^7ieJwS&@(b7E!JdsqZL@q9DHf2A`tH(EiG z4G^`1YKWR)NNR)Pd@vr^)hGwClQ|yObq|FhNreUPSIHNsz8Lp>?FcmlOYp*ss0A#s zBNoiI@B!1rr~8P8FF<90Fn*HHPTT0=osX3Sj++q;Gq!O9dG51{&{d_|uXI%v{Szb`B<>IPz4a0Y1XaZ~jMah^14@kzgqAmJT~gSk!&uGY}h%v3~~& z4;w%xsyRX}HN*rx-CeSV(UvXyMwsFj6)z7zTR?Zm7C-wYb+7wS@HQFUCQ-W8)!~%F z*aYO4vc%R}%v)5{)pc zWxh+eCL_=@{d5NXh#T3?a7TttZ!HQ!URPe+S+BxhBa}933drO3+z+XaFToe#(MW3I z)?XZs4&2{v++TM0$l;Tzb6$z*stpb2S}anqamBve7n8yF=d+VHsW%x|`nF7%J{UN& znXVQr4eK57-bSv%&iZ9o6+Ez%K@6jA9#O$9OeSome(IBQR%FAS6Xm9ib=l#@BYWsX zNK{iW;r*TBQZ*Y0jH3d(darLps7J)A#~`4Zr!El#266Vuog^HGM>^%xs(+d%WRf#n z1U?NcI!mF<8JopQo(fSl8S1#2pb`n>G6mj0V7QV6?Gq{%5ZSWfer(Xdq$rsA4*Hz* zIj$#7`kxb4G3^H0W3N+chFd=KXkUcP^$Gmvl?00+gDCv3i}&F}r9hc%5RxF~n2OD9 zsWE8!7U9;E9Yh1Ii zS$50*&?@=sNxjq411sVDVY9wxk!#Io9T{sRw?RupJj|l3n*R91&u1LUw}Kz5lIf^X z2T$%JW14MqE`P)yj_-6U8(LoOU1*KX&nj5`i1&n8%ZwME#Q#kz7N`{=~p|=Y)p@3?GVBJ3nD0V9Z&a8tTZBtONGGPkdGG< z6%|BgYX1RX7G~&YJ?ubyC8j!mhng59aa~nQGfY6?LHTu%2s;jb!+^;X-+*+YSQ(6E zi9l`U9)8ZlmUxFJU*kx7xLCo235ODtn-4P4BkcH5&z$62}iBw2qi_Z*KGkGf{7gWt~>kV)hHEclTBep z<5njPLdW+RC9y}pG4AC{zrq3)qZa*}p&9j{2IaW>eu-EO+=*~30cM^(DqPG>5Eh>G zdI}A`33j2nzK%XeGs0SJnV+K*zbw37=zd1o2{qavl1So7QK9Z-Muo68RkjnMlEfyt z0X?8;gq>?u;7ea@h!zjnj`b0)KK?*K0fq@zg`sJ=cJ_2lvw$t#FbD_7DGZm94M z&EjmeL4Ndb44y@-}lv4Cny%R|{jXx6g3E?>TbH4QY$wu^0p{-w5 zMyiESNq`1eM7UsSu@VC3(|SAN2tx*OM;*ZMB-gHduturKk(TQ)#Uh0dEQ4GE!g`h9?=n0L@JaWEG8Vt#5{1to$0lwVMu-%2Q9@PJYIB!C;S64-3e>VXQ9zyfB)}3 z;onAuxLfejxIcWZogYaw<3GS^|9kE5^u zA-DcK$z1`k1%_&r@IyNZCh(&?HL8mfk1DJzE&KjaMz6*jax){4Be}=8UT<-e{SB_F zOh&`yc>ls(N$&p0dC`JS;*9HY<_W9Wl_I3|T8ffDROJ$Sk;;HN$+C{OO-1qp`%S>X zk_4Ld9wPVF@sqpsETcH)1hjmkP+Uqwr-$9!agqY@>wth@(b+Y$?Hi)%U%5-t8m2~b z922=o)w!^9Owx2xeJ^6{u~48~_JVWtKS(ah)Z#ctb>C_n+Ygpv$VD67nmXE82LY4W zemZHScv?xxSUwXb%>j75YYb#(T;`%KxvWjwFBJAW0ryg_sUA*8FNsc%R9_4b?AyAq zca?=Uvf7TToAY8VSJUs1-mBQ6a=Tj+zqmUFxiU(2b`4`u6|0I$`RZu-)KECA^Oo>p z+N@dl)QXhYnD2u#Pzeh8ERStUG*B{R3;T0Jq)cGfZisY<@x!~j{T(E2sE56%E(wzt z!a`t}R%B7xi~>lstXCCdG*FF7MkoUCLQ@FUR6_v`1*S5C@!N978IXoM6Oi*${4TZ_QeQ(NYpm_BaG~7a5#T{flL1r~ zFpfZ(5kW||uaE2*8wBqgW2gKsb_n;|zlGA+1v@1GGxVQqjo8Vbq69=^!HtsOFiy86 z%Zv(*2jOlE{?m`D6*(ayszMRAo)LV?wsh<=@F&vyw-7e08hQ+hE+SxZGZn!@=XiOn zbFj1T0{!`y=x}8?cLYj-C%E3%XbJpJw9V*=lgR7%IO2C}GVM3gsyGtA2+UcRc=1sM zpS?X6vp`|B<=8KdGBv;Fy6-we!s#EJAmnA#=MZpN(=ppHmtV$4h-<)}>0ShxPm0{m z6yvQ4X&|S#%S=h<87BEr2T zJRt>gb6Drza)Vh|nIcpnE7M~HDDC!49=&r!uM1lTcXvrh0Ov@ctC=ukz%uL^28dp~ z5To#@Q+?B-?fEKX(o4s_M8svGnAQFoi@jESWL~3?Xa?A8#V6ZX3Qq)%^s0DB628Na zO%LfMl42JNUcGb#u}YAK*Hb5EF$M0g#&^Wf3rUATGL9?NpLmwa0%^!3)Do#*UTG~_opI^#%5gP0qrH$u1Cfb^CK@@H2JC!Lu{#{P6kmBPe7OU}5-A?dD^11A?;vN(rySet&niIzzb}o67F0yRL zPHUZh$M>To=d?iBblNVwX%|k5Eov7tVUiqxQZHOT>S$!_RY}(owAjaRKFtX-_(BDX zx4@cOD%0Bd8-6OV@6)1Q9%}3Y*HoDr@G|%_)zdC6RO)c|WvJgu2*=ObWv+%%D%6!- zvGh&7?g64)b-bMXyo414aMt8w$odK@w(Mw=xapW>7Z132-IPc5zY4GQk`3yp_>B3Y z_R9(epnc>;Yr3a@p=&y^?=tI-3a+M%%4%i7#dUG@{TPFDIqF{{kF2zNjP5+zf7oP8m`{_{pQH6_PuNx|(eO8U=-4Q!OTw zCIBv7)OtAIvsq}wQ2CP)@?9xvL7cjl`vl*Y%6KpxoZ zir!hX#pcp#6xOaR4q7(OM?IcZ8xrrIO=8dHVa&tt-$dJyj%g4`Y(cv{MGq5t=m!c+ z+pZ_@aGR}53uXp;nj?Sdk=TJ8^4&;Y76jL z{YyGxsz1s{Du3GhHIbyWK47`+`nee~T4-br`I^AEEk5hiNupQ*GsIUN%j*|I@4GCv zDfClT<-OsK#)!fIp8y+?6We_byZ7W!G?1IvsIr;@{n8Jpe2X;6}S%~T_%6mNMbPwVqP=OIFC77M_Az|*hSI=s^ zd=W8KO*N4#z}-b;Af9u;QrH2z1m_Yr`I8e?6%OTHpb?@LiIWFJTE9G^>`tOD?#7-c zoxxPdpqY1^PBeF9c+hv0)P&9VLwAv#a=!zMC_I0$ia~fWTJ$ri3!at0PAO)Ea4rh2 zg%lPw29?xV_NxRS;U)jHQyS(pl!kS`d*U{Hxd>I(fGGG{j#$#~RO{}24Soi7$4^b> z8Mirv2O=9t!Z^YWUg6rrXbJ=OTYo7xG`LPU!RtX<4+;3^Ja#48nIe>av&JN4f4wZ} zYVae{eX+$u4v^tKgz17Xt1P4CY_Ew?vuvS;Bknsl6T9*D1=bzEiHjk2fqF&`F)d6@ z!y^*f*l2A-9iDqa(?C2=Ey?Q@=R2OoT%{H<+*9O?H|cnD(u6m48w0t1!bI3dyMs!d+L2*bHC#cB zW(wu)L(28`YJ4ReTj8YG+O!;2*>(!k(URz+Ir}?0+L8_4(b|U+VEUEE@7Oc(QpU8t zL|Lal)amo_(tA^+j(Fr#m;!>z)FhN%Ue^!Py_n{7r;5v7;@Y}$U!eaBaQb&6NnduS zBn12ex`O>P`}Kb|lBQO+2KxV%rDm;s{a;OFb@$#5y$evv8dfeY4v1QwHGeSLWULou zFkn$>!esKE`G@`>?Ope^xTH;AN6EOIN;|$ja5p3dJx@OS|D7xJ$ zRWn|jU5cHe7l|HgcqEjl633}c&D270DL}5vfO%_}mEOYsKfsN03|(xIw||Hz%>S$r zuzst7VD2FFwN{+xEubAdu^KLERiTARH-+O70#?+vSC{{3H_H~y{9v~T$!Ox@z_RnU=N;a}w7CMr7ZO@Z z=slhlTqw_6HiYs*;q~woW)u*u1V6DM?bzw~ zq_pFpU!UOpnAhu~b{UP&M098dgz1i>b(I&zy=0ehHCtvJ4HEoIa>|@>7c(B0yOPvJ zE&G-nra(D|`Os^IO9zU}M^oJG{;DN@*KO*$;Z>w;+B@o`&zyN)zbpxyru~4D&iN{_ zg%J&lM}4{q^YsvfhI~olw8ogy?TTTRQhk%N%kOcvJa?21no_y<{ycCSE*omhVw61jQoaeEIJl8t5E){MkC+}@XYriPIsg&5>ttm7~r)X`T=o6#oh+9Jh$VF zwhNas`l-&8fP2;C0H#39t1`)Ds6aDT1PTp`Ep?Ywmy8N&f2eqXgRUh|IwD3%p8{Ap z;7^d0_GK?lyMggnX*p7@`JLn_NN}w(QqwRZ4rb)4CRhY8MC?$uE=LAwV_yIpNYLGZ z@)iQx3>6hH|0{)~yvodr30ACNz^FuNtr>`bJkl!U@#CYF$p$feI#1@1dZ%nbkynQ1Lh%?O!*MN=)v=Y;r8MvA^Or5wKv1O>nZ$GXrqWL3^A5bxOunROZ$hz zA$S*v+!Du~^l25x4plHi$LVwWJo=8uI&fu64PPZQQrC8twQl~hcTjUVM6=6~ayQCj z&-X(B=ajx|VAG|Jf2;!J6MTkMSGuppMIPF5Y&J9Pjzm7G@dJdQnRS^FrXoz7R?GmA z#bc^92F3v)<3-_fds#VeL~d$hj6x31IsB8mFMc)_r-J=9ucqwphRuzp98GMKidjbU z%MAGIVaPT|^v}yPcIYn6ZH@VZcyWQ=SAZ<$t1I6DGdBNkp#Oh8&x+r3oB8>BN+AB* z&APMAzx3w+`hkArUhAR=-p9WqABjd4Mv7yQU{FSi#N&p*aB?a90W{)-94{BE+dCR7 zG2WiDwYP*hmjX!POs6)cCOA3@ZIhgwEG;sayVybJ$qidT(kj@WGd=Huy#^0fZE(|= zetlT`NEU%?E?|@12hyEJOsI3~%os{`mvk3Bw2=t3t>SuQWY9OFM>pOoiyv2QEM!Bk zN$Cm*v;!zff=2qv$h6HEvFV6=nUn37-TAak)LZX!vp&%Qn}FG>OQxvD8)0rjoUc>F z^(~<^8LTykeC+*UO6@}*aAHuF}Iqh^;CeMKMBu9&JVjcAWnJ+ z8I33VXf&j5sqB(ZIB1oO-!MBq#U!Lh5RnjDQU9t*PBxuq*%v!$KlNIqTGGH&*l14r zrSM5SvT70~$Y4f0F;wSmbe{Y9IgDW%OBT~N_gAp*cOU_5czkn=ag`%|RCJ9g?gozu zxzrgcT~hl_$@!h|@m~1W-wdHRgtD3{o!w_WdCT9UbMRmlY6%F?tqKK@LM&amF(q+5 zFFpdG0r<{WQJ+-JJRq+2Pej2?$$$=XiH7xOl_sWCf0Q!b-3_m(EuRYA8VLs zn}L{!;ikv8gfegE7TQxEN&{S5`loh=2K~1lvFOhegEO&28$sQ)(IL+?%4ByzDP?tm z>`6HHt{Ic@&v(`zL(WOP1>KA+Vi-9G9*wQUVWdPXVErE& zQNh<3JQTUhuJw*AT+m0&FLlY2UT-w;ogV!^x<12=gP;4XBEhN6Vz2;ic$PG}|4vdzo6Guj zcp$V068yU27Uwj4T)fE;>PWBb5Gir#MGSylcUQPUG+(7N8!XYs&qQr)PHrC)Ud{Kf z@Ax2)5|Kc3&l?rVpT2x57kc1Um{9qeJ`x^=>y4FpE@A6LiY35WOPO>Wbo(U2tN*k( z<3e)w%=&=~fzkilZ;P9=6|KIV-A`%AQnOTA7f1Vn3uhII$eQa8*i)YiM~qU+86<*Y zC(&wuEMV(VjYbQSVP*S#a~wM~;j#NeNKxf0u6ez;pPScYo{X_1UD9Y2 zr!clggWk2>FvpRSWkAP;xe{m~7xsu=5k(PAbI@#1JXn{E@CD@t6dPCO^m$A6Yw!K+ zk4W!TdhbtxJC5TAC5AraP0UZ|n06c988Z9{5F=Uo#wzyuuGb7m#mg6gHR&vx+b_P7fr&tLj#$SF`wOsRvF*b4JYC;UHd5} zRF?o72Ku!Mcclj~V=C8(Ta$T=`Bu}G4NM6=L6oSzbOOstHMdw~O!_P^h<@ed3=05- zGheU0bx|z}QLU{s3tiy5RB7U9e%g}}b)cLgp;hDr$NZC?fZAh71 z7Kt0D4zOh(^Bk(jSLfWKd{rEAP-8gYPHpdEtPn^rpOyyALP67tPnhNl8YXk1(nj^X zg+iIXl9jO8vh?%psr!k)zXjf&%EHyw0h6v-57g)hAc>56W5}(*G(Mm+hL8`CO+y5L zB%zFcw{!WDt6-RX$PUo>$-x5%{etJ(*&iYs??zX(Iy?ObMRSrNgAAV7)RHaO01Mb`>19kc`L z$n+i%GrcuB+j$S+0nOW(Sh!t3+oYbdw;y(#mnvqZ1o->c$p4-Qs%_p$0 zdadjDZC!EtNFPLD*8|}zPo5q9(d;*uf4GsJdamu)H<7D1u_5R&Ksv5$ax9yliK2tV zcru^6^jnsjysw@v1jHUL6qfg&vUj@l3AAd~S?|2l=n#0!=?r~20%^ItHDSc`9=L@( zb6iE`>#kj&wE1qjHpR4o14J&$8X=9d^2_sRpuZP%7o8u5jJ`#MP_tm1Z?gyYvOnXB zB{W*9_c{)K(RmE4Gr<#ruPgishZ;cGT_uWALFFRrv0Q88CBcLmj@K1xqgxnO^MXkv zQH&5})cvghcs51&g>&j;M}#O>Pq}q*VP-A?U69-fXB!0X4+8A3IW4V>oA(C zNXBttsRL;Oot9^Vpb)Lj2C|7=kI*E-s-ky4A#jri-Oa6ZbT^CEFOE0kqx0ldhoayg z-Ky}qw*4#1yYuCoX9xztPVVDTy)=D4?5X)mvA{&j9P0SiG-*iAL#R%H%hkKYCYd() z&IiwPRLOJ$jctkp2pK3(^~jWbb9`z z|L2o2TJ_i-Barb31=Ppe$pKogM~5BXrlK(g8hx@Zx6}SdkU|Oh)s-$Mq9TiP#v+H^ zQ!gRiP-#H5C#C;Ure}PAg#I;3HUg8ysIKE)Whkv2M0}3-5$_2)55v^ik5@*gPEL=Q zo#-S+Ka2ZkDz-~l1@CPxO<3eFErh{XD#b@0t-|lolKsk1mdEN)LUPm*18FVnDNDw2 z3#)?iR#+BUM{botS6Zfxb2=2?P2gKY1sA8iQ#y4RsB*K$mHbq(#s)#iLyG<+T}E*l zp$T-j-qMR`_W?5miCo~WqNwdb;G9Wk(ot_4|85)Stn5X_>b`5bvfi1cvhbq~6k+D4 zdn8A99`^}SWj))7IT2JPV!nRW@EVS8tK}1sBdwE^Xqyzm+B|aw^f5zCY!)tlB7uao z4>^oiJUMTYVXh?Pd}_X2Uv;C(-y_f+5s3yW-q95iy4@5_D3Gi*P%e0JNWUp;!%OK> z?{ISs#+1s`1JNO0gbF1%b!{PDtYTeg7Mqu`jvPTd9Qu&CajQpN6j5!m?!J>IWk9>< z$A_^#*?k!GNGm((tX(RkGp7M7+IniW8G2+?@vzX+!KvQ{lb7o9s;{ugH2J8#Mu!rK z4ew4?ZlV}%P4fl<=~RY}u9NhKxeA<%!KnBc+nBRu(VRS0o+0UqdaPo^3TvnBhFAS^ z6}Cr$FCj}TfdHdhrU~~ufvkFV01(UDf-BD1s3tyHgaL?H7PWDUjFWpT9N>PhDn29b zA}7)prUW}4lv^RBzvZ%$l$4K^tS*cGkMR|p**Yze*-q-anf zSx6PaU~7n^L+i+egmOd#q1X1)I5wUgo54dLNMU&r?7ALMj>WD|aFz~b5&$rYGbf{zI8MyKf0#Ei+l5nz3Vxtte5xg96Z&E$qhLo6FEE;1Qn-wwAZi=^KMfO}$< zmYLM6Yp;jX8?=fx7akT3(2k8lTsX*)e5LoE9c*yFNGhhg6qc!3VXu^or9%~a1ovF054FFXa42 z1-eV|Jlk8DolQ_KyFtPTS45OM5QG6!@?7Rr-SRgdj@R60QBZyh>Ygf5w?(<_;)u6& zEMQF23$*;g`dwU^a-Hi$QU~;qpxxv#nApB!;w*#NvOr^kwOdH{_gPy!HgguD&G|-2 zF2*FQFWF$=S(G8v3FPLG5=9PKAVO;J*%R8OAozh52cL@U0Nb?RquX^>~zt?yB_{g$9v#e!`>-OAbaHs;O84D@#nuMu?~r$b<8ZunY+*VRC~$p$QnU> zwN>0T$N%jL5cq87mq=y*m8`?r$=vFf4I4f;McHn^C(D|^E%E;qvG0G?^&K4a-GNKQ z9u;ZeR(O<_UDXojY@-0D7q9o~Z1U6krRLm{wRngkA)_T>5yhB5s6=W%EHCw7i)f@b zw$$(?c3Zd}owxM(&0^FwCtI@Vot}|zr`>+k85`114zHqqF=vPP$hg?yYFQtO0JNXTw+dAnr7;uaci!mMp|J}=e_kZu#l$Vo@oE#Ke4hys;pd|;cZ@wS(JZ}htc;5{H3*U z%%fX46|vUGxi?aKb>Z*xg#;s+-HfQ`Ss?MpH}HaB3&Uh?i>!7R?9}HUp}(@g;!NSf zt425t1d{_ThNnuZE5FFw)TE$;L0fc;J8o<*e>9LAdcTFo5JYqswX(POK7kNhCCc~k z%@VSphwvjx^>o1xM6|)8{3V*E60nQOc%R`IC`ku31XiDELL5}%Ba1bej^~}A+KXQ= z6Jmb}H56|pqNkPOdD-vVwlosImblqhHSBVT(VgB*4d*p(x9Wt{6l<~K)JJwTft3Ne`Wrnqnv(?hA;nT`7_xu=|m(CpGcbY38! z5tG72a4iAj#d#+)%{=DvR_>J_2FE8ZgO@D#t=@)bt$eCz^6CgTHLa3I;iPMW^Vbb?qu#+29w9ztD8p& zQ-0nJV1kh+CsY!BdXGRoSel!){CK_j0k*HGQmv5|oBZu?&dQ!0pNGGo^WXLs<$TJj zK>noJjfzCZuZ+lZAY1n85JmS95zn4dc`SQnM_pd~q5`pX1BEAg-7XJ2x_Rmu8lhv~ z@uQF18K5+01$yN&gEqF@nf`AC2?!AhiCt?<&ozZg)b1|1JQgM^vKjn{6RfS%2PNC~ zIZi>PYPj!d53qKs>`$FHN95&(8!wmatz2=?K5`~?gDpCsw(11c1@-d3U)^UFGJph^ z>6>*BjO^L|W%xqMH|sqC4qwdh{~gHtf5VrpfrYW*gGY?lU%`&Ps7l=eucu0zXIsf( zM)&I=;jEG~u`@*~e9g>_s-wl?vez0yPv<=YCx;iUZXbsV9}gW4C1r7ZJl)l)KMmd2 z8aZ9UlHylWMYpo9zm0X2U5Z&|b$4-=tV8g}zpgK%5pi9t8^81$+3_Eltw{ym0kfUp zq`p;)$zI^-wST_|%~KE`cBZsF#oMy~1lwuUI})-HGf_dc{i4g|HLbAAZrr;JeTDS% zCC-EtX+p33seO+2h4y)hypv&r$~_GV(2?6?i^>A)G3C^$J>{(CY|E>f#~O7y*3Nmi z_U__?BYhQXn`^kd4xz+e*;NWl)mf%{_BX2egykdS;SMr{@2AunxcL*zY-jcx$d#2> zUxrsB@|JTSlBsOEXb-=u&qZ{js|CN)Lm;^HC*OrAsf+04CeZG)H7_Sh+UpqV@O)>d zqRa~PNPK&rlSvFXk4~Eq>7WSK#OviY43bJ1nc6tDd33C4zk@#RtVmcp3yZUzP5`Hq z(T#(}g7&-$nfPP~(>k*68b^&8>H{f633?QY2wam?3u|w%f0{Rh9*mcIQPER|9eHKK z2}_vbveLqc*GXkXEDCQjOIRTj=Io*YHiCng5TI?~N#(*7`~Eg~3{VNnhq0ag>&!=< zN)di)X2lESE#hL@<4HU@A7}mOu_j|~<0PIjO&K7jn~EsFC(kYo1hU<{#sjILrG0;;RK#|$H3-9o)d{dHP@3)C6&6$i#0kJ9rV zDk&Sse0&gCZR0f7udO=Xd3)XG67Z z6eSQ^PbsVE)3dJ52wxa+8n@+T=TX`dM-Pq(W2j^I}xkSlq-W5QStn1+fGb2dzB{ z!m8H0$YRy<3XOMPaJ&)Tk(Kbm67->Q+)=Q5jUq4PQ%c(9rs7W)r+T7#j? zgpH0h?9-RN$@cX}^)7jble~%5KWo;(}P27A|!@2|ze*b$tsH-!()j!HeF3fnHRM^}Z){(yXbT(|iPY z`oQ3Eg_UL@*;3I_9m#{r@(4@0>7M{+U$#FPyKV4=T1!#u6wAteI`|QNfalv2D?>}{dfc14?D%&g6Dy?la0~_svrYX0 zX*WjvqL?|Unk9A>T0JKW6xW_*fez2H20&PFO}@mc$99gH9}5a3^hjxsMvg&8I8O}* zUT?5z9z?Atu{(-g4QJ#?7oKMf4sG>(pA-LiML-Jtk%O_Lt+T_!UTu9NBU>AKMVJWDitUZpiyHgV)ehr$(u4dB9ZMJc7aI#^uvTtNac<`z#ep}+#n&rk1P zGkFaxF$5SSR24doAQ^Ye2A8NJEESrZqrYdLh}j`GO`fLh*+?ZC*?gZ($9mqF6i2eG zFFTvm=bm@*axr(0ai^Y|H?2Bs)4^-^OEaHgid3b9g$hibC9@?PiyZ& z?u~0av@B_r;4bxDGh#bd6cSmsqMlZhN*8L!Vrvg%U`pJ6%P(|otgnM7S`C-?R z6-S-k)PgmSGo(j2%A;TY?_TNuQw;;dpsb5d||D~XFaN{IvWnP>3E~2_~1?V zFHV^u_Yv;uSFXnG;t4`(6!H&*SxTQz?GBPNO2YF#BND*ylj5yFjyag{K|MGpXy*5c zD!_CHZX!3IO>hrQ{fM;`i|P<0)pPcIYFd$ak=r||eMf}WPvq`+xaWFsol`(x$(Yjs z@cN5M?E=X7Shs=am#tGp5Hl-ut*%ahyHc|1+|&Gwl<@POs!Rb?1HE41zYd z>(9eS#-X+`ahnj&7&q54V`3##-cQvwfX0d(By%d41(ZBiz+rFUu!J>pmrAGDqI36? zeU`P=SV+t9UZO{z*KmSbNKa4geQLkJq&W?fyZn)XkR{fxB*rtPP}dcGnp<&s-vJvI z`Rp$;2#qB)X2=9w3>m)lLz||Zij`7@CXhAl!(oI>v9wLe>C3(u4gu#ZdZW~d0qU%nJS9Ism}jXBfV$=(KuTY45@+DyGe z|1}5*PjruooVM&J$hgqfM!7E5hNMf`&ENXf%Xy~?O*st?uQb_d!vYS6ch9D*t2S*Spn+O1AniGRQ>KrtW&-Ix+zjRE zpZZ9`E~GeL#9)eaYCpc$!-gLl@uGB^2QtszB8iM)sB>qGZweEjLl^p-@O*VlBTA0J zI^hmX^`2`d_^q{p=2F7i=&B0>_X)X75EO1KG3P%(6Z zQFk6Z&Z7!7$4T|1Je;z*U6jef&uML~!lU>w;c2T$pXX8>*>y=fyZnixl4V%_-2qRl zjSkOP^Lgn2b{*D{vj&FDT1%kXjZGAeinCnHY^Tk3d;KxyMg}8R7~wF&7?OH~s!)z@ zKR%U@G?)DrqIQ%el|*zbrXXHjF}v;x$~uSfK~W5CvW`|iJ6ItbW8Rvo8kw#J1wjNBCNgFHm zSyn7o14CUIJCaBMZ#Bl<9!t_ucsl3><95u&nwj-p|V=A_`9kyxi#NyJps4S8Y6)B zP-q!qBk3@o39E*(Hb!iry8*qR9cuY- zOC7eAO(bQoloSP7wYX9%N`tTy3R?UcnWiJ~GN0V)Y#S`?sW2w7!Ls*XlKTXNEruQS zV(T*1$%Fg>kl_nq;D|$QP80mt^`#hrg6F0)w(ekh+MMnCu2yWg9dKDQhB;$1EHjIE zz8zhlPhP&w^2Z)qa$pAw+XusaTBbD47}d5Q8)Z|Jj7#8soa&cXJpj+8CqPwsbgk1)Ik*`1gWepvhW~gDIBY*afie{LETsIytX z+iix$X^E)Me*Y=JVLQiZJph3fDdf57yW)!Nm=CZQ@gX5}N|S^;wavun*-c=L;+ebw z-Ev(MSRr*M90!-gMEgi5d@^fXf%xG1EubuW%os9P2ou~+p#7f-m_N%TevH<+a2D+_ zEGPt-4D}flI`G&NxD(U~gFD=E8TM?1S9& zga-GET(_?>PKWA0|8nO;9J@t=WEMOhig#KhlM|GO=gP@ zcJQ%-G&BMx)e+5}#&CW1wztHHJo ztpgiY&1#v-tS0FahP}qY+IKiBscakJ8~%}9BcGBR_mrN;5`_)kxtY(E@nD{>b~)K# z^Jl+|l-z$#m9jD{?85*Zo_To=A|X)_zOV>`q1Z5(&=MjvKwD@{4WFNx8ctK^ce`~p zqOxYklvXtEH-09QU$ub8Ka>;~Rj9w;CHe(Sj!<}ZAChLw$drXV`WQn$K*b81&BLsf znJb6GCc&O=(QW|rIqa>fJ$yXm#TE|CBldU6fyUG3k_)g+>y{$ZVsD;(RG6S=Bs*U8 z-PBeploQ38wA+!d?SK0C87!ZhcW(NjB_5Lm(z%hwTx;FoZ5Lj)1855{hx?Mr3T!5c z3IF=z7g5TGtW>+jbXhu1)bzQE{V#(tUq=sEr&X{?_v)73>DMAk?Y@fi+vmyKdzYsa zmViOj77}WkVoGu)tZVcvwc!zmlb)4Z)_$)^e;MFiK{YQ$4s7z;k}6b7B*Hnky3WKWXZQSw9V(iPS=Q@fPejx>zbC`0P)7B3{CQjU>aAVKVKUmB{!g;`$Lpq zYvz@-yu4*n3c8(-oYj)>x*Bw>!N;Z=s5PaPc_;@o6b{XICK^|uA+>4*U{waA2T0cm z?uddnwHHH@XLyZigOXRbqFw=6fwMaV<5+LP6E(4T9VQ5!7NC`?DjF$^>%R~srrD8O z1Zi99g-60E4XGt%+Te=#z&&4Px9pCU$bGSq^EAU$y6~R*0*Ytktaazv;ru#{?!X)` zD#d64aaOvP;`FjU<(Xln3>$%Kxt|ny@YDBDrj}rm&|IUH04doF zwv;Bq?p0$~`~|8e+JG-I#dsMkNR4;97Pg_x1@|$FORw^p&|P}hVkQw&3j3UNGm;|U zZ2Ji2^g1bD<7OjlCSLfrlQcWoxTcEvlm(-Ao#rfBF14P`%7%Iz@S0pFLvEpUr1FTm_%XcYwzgK5 z=D$X{4;5J}GsOV`sTKMCv#W2lzvkHiUZuu8v2&t%;M^6WQU&;(-*)>3Voe25s|U*D`H-16@ z_>g0}OM2RhxlUMuSM@f{bXc*2MSM@Tq7BI7KQggAm^9 zH;3MAsJY9!Z6q(aE}utp^vo?K!=J3KiZmt(NG}dF*wXq6JBGbw)KDxnx9ryded;%1 zy|R=%5@}Q2T5OSVWCX$TApl)_a<0r4pKxpJ)lRgv%qjthzKQqkS$@50+Z|ly0PfBE zCoptcF2%dBjW3e+epRqc= zP4tWE(3>Z%)LTKTTk<6V|1<`n_sl^0VpcZ5OpIfBnh>e3qAME|x3kBxp%fnd@+tu6 zKeRl1hQE>l3^!wu>c~yxl~hEXUNuI|$OpX^hUbHc6;83 z3h}cGue%ZdkaM=3Fmohd+iJUr4j#7W;;j5aUI9S2j$>MtrAa$Z)WVCmZ=4P8eFXg?<&`DmJ? zD*EU(v<3@%YrH}%PAcypd0adg=-(gHs-)?u`R3W^_#u_#I^3m)LYLSPwhq5V4hvvtLUsGF{;Q9H#lR;co6-l*Ou zOq4`?XB?tfFaSGy4Mwma8L9&cLMBvLFmWH0DGj>0kRNIWa0w5mSLCkyVG*|ii-k;U z5Gkz(H4NQ0-lUb)3mkiAtVJtR7T(4bkhzjdH2HScH&|dqwU8?pzz?v_0afsbvG4Mdl|bwv7; zZP4*&d7!FLg3KhTsYw~7=5)<|?s=rTUCpB5@LC!gP0?@nD*U&|gWK^TlF_L;7^cC9 zu9xVo(iYJ0tmhD6=s?tkb02g1+aWQEM)oX>G&h7Pfu_TLl(>*GYe+5FsI0sT`2R}fgDAZ66ywm zqP)o#G_(g1Mychev+0jvW zgU52MUFuQQ=7cCfaH<=H0M;}eaEZxDzyZ1~!-NAm_;KGEdTg^pxmVRN(r2A;n#>j3 zgTlKw|7v-QEsuJ5SVQw1xCJ6KyG5{DPVwakcA&TL)lfsoXSj9F_P_%nCfBP?^B@lU zxy}!_jkr<)?SSdE(^)%@%mEPx{hER4?FpKxk6S0^aGor_e(>Jg(~hAo5q-`doTw9> zR6#5n8uf4bPv5`sSP&RyW(v|(9<(8tV%cYbNie$+J{&uft3ITCE{GV;>0jA!tA4Dh zV+nF+7t@^{mb_tNVPhlC1~!kRM$N~RA!sKjh;wsI+RX8Sey<~pNx-XJtlLvDr`e}M zeE=C`AD}yQ!j?Q6iX4Lo(m5XdJirSpD5+B1l>r0or5jY!fkLtMhUv|~(q z#v=N1c>vkO{7MHIfRrDHaF>o=9}-`H-g?kHL=@^P4`I716aA-+sh)>3uCtv}V}16C z%0$93K5l)Ohgbv?y6wd$&#KDPimi#u7^3n@nBu^o!5nFhFmWI@fx;mysprz7u&qF9hO`-cFFBu~R(;1pk;sBp> zbF?@-+bekXxJ9>?-V!nSrZl7HDiWs8{q9+O z5S4%-Hp=HJi+EZiX$Jh^>@6fACf1xo&zGG=udYZ+;0}hZ_$%2F=O6Py>#cqvZSV91 z3B2K)u?}iCS3SNS(=N>C?;0xdRiAIGDO-L4%)XKtS)xjmA{2!J8Sw?u z3D{7omtI5PWBRdTXwyXJkFT?$EL%#0;L(Ukk{-7th{vzbqDrAtQ~3teZ}oZ3(Iopk zYTzTmeWbOZq%Ue(|NyfQ0Ve;r@aoz5uAcmUY4wyle>sM zG9uq*9G*k@d97VbC4=Q`2Wah&>PfE%qPt^OSUx6NyYOVP2^fd$l1@kSCsAqz*x|K; z`-OKT=+PQVAnG+!pyV3Gmz4$k0`6x=S+A1JynD>?K@eicCLLh%NEHz*CP$OTWcj^a z&ku5}Y`L$vDo)9_xbV-NN4*950(k=~GWr35aW{l0K2mQ@4Y<%0E%=sSg~OU&fUexX z@*(#0lm8UV;y>(_zB)BSK?Ohx^J~Q!gp@*5&V=Fs>)G|^Iwvrc3g0utqY_p>L>Z~V z9d%{R!=R;n$>cBQ>u7>t_U;;UU!)+LZ!T8DShO{nQEuf3M>Ra8#fCkVdM_SHRDMj5 z#+##r&W@ZxU^Hhhpd42FjPm3jzkbJZ?OtnZOXHJq#57obKX=F^1T>bu8J?CFG%5!e zKHU&EAli^b)=q&hh}C_GzK8@PqF4qO1e;Kc4=DmyOT!wDbL3TTyF#dyTfc&Iw7Ei^ zpM4?d0r->bEbx^S9Kq%1h$IVL%qpqO%CA-!ae6tJGrASmv;p+g$%{&8$J<;r@h5_O zX9E}nn?7p$;7nv}T=q&T(9~-n{S|{U+=t%M&53zi9`OXQ#qjHgIGw}u6}K7ej0IEV zm2}BIFPnzrgdO~C=)2Li?4ErQ6%?6Zq(e(xD7WBhS<(>Hc>_r{prxNBq)}3lAfOnF z6`mdC9I&$rxlPG9jASW=V{5H#+GWuxwV+v=E;FH|RMLnRJ0t|E`wllrr#>QN8-gLq zG$NNW7Cb+6flpkxgP%|<$t)Y39s5$kVi?}Ru{X0_t2m2s5MZR6&x{=PhDMIeY%H{* zThdpe3zy&P#;moc_lOK$u#8MrgSv&#D2OQ?YL{Xr9K`p{m zwa@fpUd0uqkS3(|vLJm;mSuv_YHFkT2#z$4=L@Rfx^ZS@tBY_96(+FMc#taWYVK%( zJ!z)IkQ`iWn8R*^dJ0zluZ!`x&;yU^d{J^Od==Z*JByz~p7v}wB?@#E(U2FA`I8h< z4D(tjP*Zff35tcke65_k7sG8YWoj-C}$E z@JFzQvYBk=L$2`2JhEwooTuyUhn`4%DI*1-8(&6(NI1R#RU)`CY!6yT=jyF?@j-Z_ z+L#xmmR3cTVHr({-2Kvv-BUsH@#rL8e{ssomF# zvacf|Q6&4%BS%DIx8E4dqcw{ZcphA81MjL}ZbPw}IQZcq?69-U<-3Y6lV z#+NbUo4>A%?C9R&Nxl!8we|5hP(Af-GZtD}&l@CG00h^>>1N$ZrpGGG@U2$b_}A!S zryxG(CB|E6I1|zZK4?)}MH@4PU3J^zcbArUi%)_lqQAuf*0c)wK4bYgODDO7bqJLJ z*)1Jf&^Af{+?#qAMPZz$NK_PApa;GjQh6M{C zP$n4#Lfl~y=&RyRKi-qxd6YrKBtw2+GPfA0P(PlE5v6|KO~NB}NQL5?g>q};oTh-jdH-zCrb zIz-8tg5g{fm1~Z40p?v2Pn;DR1z3)_f_W6R(&L68_*NXM4v72iA+h=Wtg{$taK7lA zbG~!#i%g5SHG6QXz(S0$SV9rZ$1po8eJ+S)0dj^x;n=M8aQheg%`uM;6t;G!WZpVs z?JpD(37rc?+?lD7u@ympncL-MMQBMP9a6P$OKcD{@#F&Z)>Rs@#qCHKi*UT@1T@_F z(eUL=Nn!<%uH!`i6kSw#4Jiz=*Sn=!k3c_?Rs>dew)2SDT4=3_S1)_ZXqUu2 zlsf$HE3#gQ^f=E(uz405YhV{RA9QR^@YO}_DDBp4;w;Cw3)5nbe^Feqc@?0?ro?O? z!h&LziC3&D5l)=-WhCwViCAKAOc^T0`6nNyx}E7d=`Lc}w2JVIoXn_T9u80bMBrnQ z*5J;pNZ=0RcWJ@|hItssrk>=WsAudBlsRt5irEs&Q86HE7)$JLT}W4GKPmL4l5mhV zj+R7x=`OWGsS&H60~eHBj2{D?F^ut z3unXhh`I=4kVB;U@y-VwW;ID}) zv(*m`MaqneHik(s#b_x9HQMh$5OZzY)fj1h4w0DHc`Tgw;Rc$+pg@@UDn>Vh70Y3l z9Gz1bQHO`ar)I8@8y7Ozz&TQLf{vwD7+V1|S54X&)>Zv^rydpb7?~ABIH+qQh~Nyz zsOJ5)D&o9a=H`LuWSZe(EQ# z16oRmF7w^DWVph}jY=z1B8v3-jw@|#7%MOLGrJ3vMZ{lytd@&HSlmyhGWBUGgN`3^ zY>;QyYcGxn^*5Vm9c{yRk!nXDm4g^o#gFcBXznH|0oNx{eA(gdq!P#Qx(Z{dO+)gUtpmLp<$91U3h~lC z5Hc+4HHzVkcm`T9JIb5odZ=T}`RGpjAO!HHSA9{69HKP6rzCaNFhN|8GuM25QCGCzojc>Ybg*)IJit8&$#P&tQcLq9Pm@Py<s%;uWASw7g>%$aF;IRM~$G zxv)4FFYjno^z?EChaW6lTR7JIMh&s; z0-+6=SkL4#hQn`pk{CRj!#^~Iw5y5|CzT_938$RUw~>T_x)KW6gZ)KObj!&Gk=gs` zx;HvLC(Ez&#uta6WQmu&69ZAwY?zkNDq~xDw_~<$EW_57@(c9!@+23eP2Tx4hi)N~ zrYA~fzLniD8n?14xh{JJ+WB~h)f3bOLlF_R_*li{Se(s-Knk8U=5@7`iBAv#<5WAO zX~r=z)(Yd|rzw0xhd&y4P1W4`_546(her6AxOeOEtCh1_IbxbB-q<| zCI80B#l?CRSvq)n4n<{Q{KEC8tFff zi5^fa=q$;P_HtvoR=F+Qp>eK)!t9=a7s?>g*p7Te&YzZw!1e)WCO=@MS6Qtys_b>Q z`kN_2sm7*2o?)@ho?0v}yoqr%8sq`66qC})ZKdHbu=re!lsZDYT&GtO{1N(1kpHuafZIG8q>>c>55M}BHV(T__UoL51sE;H=n z@X3&|3jS_WvJ@+-?$YO*zvVxlbrAmati!;;))kllMc2r{RQG=_dMw`^^8Q(saGH$$gg_TCkdar>Dnm{=xPEgh^|f3DR?c{`8Gz!Ndb<>d?YZXBDskmfT{Rs zuBM!ZB-dvm75rFeZy-mhxCOLj#p$h?Qf$9-CI%$VE|@H-6MsXVd^;v9f7?i`(^j6o z1Zkjsj45QOdYGfaC|EV!dsE0^^wcLP?aV8q5lHFTe8T?0yDpDko}0n*458N8nAA<+w|&))`FR zlHWze$l#~1Vbv0Zo#;qJ6U?=jsic{Kq--+<6T}^HZNOo-Ks)S3-1cNeiN{@q_*S^N0}(xv~3nr7tn+M%PVi!xYvH%X>ZORF)quqL|ow+ zf9%UMJdhN=8{Fb`L3tL8iV*!Sexid8tPja13TR};Sawj1~EH* z(~kmt_wXOMJMVkR1ugkr>8s8EsQJ}_cbZivaSa#|-W=$_`%_K87Oy+g6iQ$h zkpRLUoW8%6T!71?KLLOBB>xHgfcV*@$i7j5uls^qz)9eDiVcBdy6sOL_^azu-@Zz{JkxHuO%$ZVx-bes{|LE`MKe2RQrv9`Eq?Zv0g(LXefh z46so}@xO*>`kPwdhTH$dnHf8nJL#J~MEv?8^eY+bQ8{KWutTo`qqRPS5BpYt0~9d# z+JBO5^sS8@?eq=*4V{HS;`tE~1caUDS8LE>{{yt0gRQl>dQ#_u#683RXGLwzS>qknV?0Z-KQNnj&*Ap`xa{|3zkjQu&(*5Dxtov{P`k6d&= z8vFtJv-qDo^R4*r#hW+)8~Y!+`J+iYyMelMfSWCV4gJ030-j3z3Gdski{I%4cHZx0 zUr=1`_gr(^e~4Vxc6#gq>}|-v$&=wb3Irq<5cuCP19vB5df;SZtZ)7Ey!h3E`@@dG zA%GL2AaKs0_=zp0{GUQi%&mU5u)lgmYs>v0aPBe(9{JCDUu*p*^I=H%SG^D7el~!= zf7%x;HvK)@ikZpgA5B}DckICd?7;lM<^>Kd-%Bpw)1TlBZ5{rt0le`&{1|EMsunPc}Yu`&Q;NZ`IhR#MtR>mggj%Gi#!UO2^ zkP_)bGXd z1#JC)Q2%Y-`g-1eO||xekDC2^)qf>k`yu$BC++86fSLCnz;9Wsem-Tt=CS&rQ00$+ zKb@+t2mNc#j33CSrGKRH=L{M@n&2z`*D(1%@P(CshW{2c|5x&_F`9pn1MB~Y{3BxX zujpR`&i+7SH2o18c=_;G_}O34zeXbcfmUhxBlP#Uq`#7Xjb!+PY}fHeA zKM#+8|FkctHu!t=|8_+Gz3xNo6#e#QP8(I5VR``3Q(AJm8Xe{aRFc^$t|_XRDce^33s8Tse2;n(fR-+;M*;y(la$ujxz zH!ARTUl4Qa|5p0VoBYRde?9rXdZT{><^mM|fc7uzqX)px&H4AcQ2T { + let addonActorPool = new ActorPool(this.conn); + for (let addonActor of addonActors) { + addonActorPool.addActor(addonActor); + } + + if (this._addonActorPool) { + this.conn.removeActorPool(this._addonActorPool); + } + this._addonActorPool = addonActorPool; + this.conn.addActorPool(this._addonActorPool); + + addonList.onListChanged = this._onAddonListChanged; + + return { + "from": this.actorID, + "addons": [addonActor.form() for (addonActor of addonActors)] + }; + }); + }, + + onAddonListChanged: function () { + this.conn.send({ from: this.actorID, type: "addonListChanged" }); + this._parameters.addonList.onListChanged = null; + }, + /* This is not in the spec, but it's used by tests. */ onEcho: function (aRequest) { /* @@ -340,5 +382,6 @@ RootActor.prototype = { RootActor.prototype.requestTypes = { "listTabs": RootActor.prototype.onListTabs, + "listAddons": RootActor.prototype.onListAddons, "echo": RootActor.prototype.onEcho }; diff --git a/toolkit/devtools/server/actors/webbrowser.js b/toolkit/devtools/server/actors/webbrowser.js index 49837c5e2ac..a86ead8d5aa 100644 --- a/toolkit/devtools/server/actors/webbrowser.js +++ b/toolkit/devtools/server/actors/webbrowser.js @@ -60,6 +60,7 @@ function createRootActor(aConnection) return new RootActor(aConnection, { tabList: new BrowserTabList(aConnection), + addonList: new BrowserAddonList(aConnection), globalActorFactories: DebuggerServer.globalActorFactories, onShutdown: sendShutdownEvent }); @@ -545,7 +546,7 @@ BrowserTabActor.prototype = { } }, - grip: function BTA_grip() { + form: function BTA_form() { dbg_assert(!this.exited, "grip() shouldn't be called on exited browser actor."); dbg_assert(this.actorID, @@ -820,6 +821,94 @@ BrowserTabActor.prototype.requestTypes = { "navigateTo": BrowserTabActor.prototype.onNavigateTo }; +Components.utils.import("resource://gre/modules/AddonManager.jsm"); + +function BrowserAddonList(aConnection) +{ + this._connection = aConnection; + this._actorByAddonId = new Map(); + this._onListChanged = null; +} + +BrowserAddonList.prototype.getList = function() { + var deferred = promise.defer(); + AddonManager.getAllAddons((addons) => { + for (let addon of addons) { + let actor = this._actorByAddonId.get(addon.id); + if (!actor) { + actor = new BrowserAddonActor(this._connection, addon); + this._actorByAddonId.set(addon.id, actor); + } + } + deferred.resolve([actor for ([_, actor] of this._actorByAddonId)]); + }); + return deferred.promise; +} + +Object.defineProperty(BrowserAddonList.prototype, "onListChanged", { + enumerable: true, configurable: true, + get: function() { return this._onListChanged; }, + set: function(v) { + if (v !== null && typeof v != "function") { + throw Error("onListChanged property may only be set to 'null' or a function"); + } + this._onListChanged = v; + if (this._onListChanged) { + AddonManager.addAddonListener(this); + } else { + AddonManager.removeAddonListener(this); + } + } +}); + +BrowserAddonList.prototype.onInstalled = function (aAddon) { + this._onListChanged(); +}; + +BrowserAddonList.prototype.onUninstalled = function (aAddon) { + this._actorByAddonId.delete(aAddon.id); + this._onListChanged(); +}; + +function BrowserAddonActor(aConnection, aAddon) { + this.conn = aConnection; + this._addon = aAddon; + AddonManager.addAddonListener(this); +} + +BrowserAddonActor.prototype = { + actorPrefix: "addon", + + get id() { + return this._addon.id; + }, + + get url() { + return this._addon.sourceURI ? this._addon.sourceURI.spec : undefined; + }, + + form: function BAA_form() { + dbg_assert(this.actorID, "addon should have an actorID."); + + return { + actor: this.actorID, + id: this.id, + url: this.url + }; + }, + + disconnect: function BAA_disconnect() { + AddonManager.removeAddonListener(this); + }, + + onUninstalled: function BAA_onUninstalled(aAddon) { + if (aAddon != this._addon) + return; + this._addon = null; + AddonManager.removeAddonListener(this); + }, +}; + /** * The DebuggerProgressListener object is an nsIWebProgressListener which * handles onStateChange events for the inspected browser. If the user tries to diff --git a/toolkit/devtools/server/tests/unit/testactors.js b/toolkit/devtools/server/tests/unit/testactors.js index e95e8c0f41d..5421ca06ddf 100644 --- a/toolkit/devtools/server/tests/unit/testactors.js +++ b/toolkit/devtools/server/tests/unit/testactors.js @@ -71,7 +71,7 @@ TestTabActor.prototype = { return { wrappedJSObject: this._global }; }, - grip: function() { + form: function() { let response = { actor: this.actorID, title: this._global.__name }; // Walk over tab actors added by extensions and add them to a new ActorPool. From 60a986c40e1c999388ea78f007f05b25108a8ed2 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sat, 24 Aug 2013 00:28:43 +0100 Subject: [PATCH 33/87] Bug 887703 - navigator.doNotTrack returns { "0", "1", "unspecified" }. r=jlebar --HG-- rename : dom/tests/mochitest/general/test_bug629535.html => dom/tests/mochitest/general/test_donottrack.html --- dom/base/Navigator.cpp | 10 +++++++++- dom/tests/mochitest/general/Makefile.in | 2 +- ...st_bug629535.html => test_donottrack.html} | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) rename dom/tests/mochitest/general/{test_bug629535.html => test_donottrack.html} (59%) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 784b092ff59..b6e121fdd91 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -81,6 +81,7 @@ namespace mozilla { namespace dom { static bool sDoNotTrackEnabled = false; +static uint32_t sDoNotTrackValue = 1; static bool sVibratorEnabled = false; static uint32_t sMaxVibrateMS = 0; static uint32_t sMaxVibrateListLen = 0; @@ -92,6 +93,9 @@ Navigator::Init() Preferences::AddBoolVarCache(&sDoNotTrackEnabled, "privacy.donottrackheader.enabled", false); + Preferences::AddUintVarCache(&sDoNotTrackValue, + "privacy.donottrackheader.value", + 1); Preferences::AddBoolVarCache(&sVibratorEnabled, "dom.vibrator.enabled", true); Preferences::AddUintVarCache(&sMaxVibrateMS, @@ -563,7 +567,11 @@ NS_IMETHODIMP Navigator::GetDoNotTrack(nsAString &aResult) { if (sDoNotTrackEnabled) { - aResult.AssignLiteral("yes"); + if (sDoNotTrackValue == 0) { + aResult.AssignLiteral("0"); + } else { + aResult.AssignLiteral("1"); + } } else { aResult.AssignLiteral("unspecified"); } diff --git a/dom/tests/mochitest/general/Makefile.in b/dom/tests/mochitest/general/Makefile.in index 99767603c24..2bdb7e31b0f 100644 --- a/dom/tests/mochitest/general/Makefile.in +++ b/dom/tests/mochitest/general/Makefile.in @@ -25,7 +25,7 @@ MOCHITEST_FILES = \ file_bug628069.html \ test_bug631440.html \ test_bug653364.html \ - test_bug629535.html \ + test_donottrack.html \ test_bug861217.html \ test_clientRects.html \ test_consoleAPI.html \ diff --git a/dom/tests/mochitest/general/test_bug629535.html b/dom/tests/mochitest/general/test_donottrack.html similarity index 59% rename from dom/tests/mochitest/general/test_bug629535.html rename to dom/tests/mochitest/general/test_donottrack.html index ba04dac70e0..b09380745c0 100644 --- a/dom/tests/mochitest/general/test_bug629535.html +++ b/dom/tests/mochitest/general/test_donottrack.html @@ -14,10 +14,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=629535 From e5c08ea1c86bc3ade874ad47a67235ce304ce68f Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sat, 24 Aug 2013 00:31:39 +0100 Subject: [PATCH 34/87] Bug 905240 - Make HTMLInputElement.{width,height} getter return 0 for type!='image'. r=Ms2ger --- content/html/content/src/HTMLInputElement.cpp | 6 +++ .../test_input_attributes_reflection.html | 46 ++++++++++++++----- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index cd14f42f851..db90c55e8d6 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -1162,6 +1162,9 @@ HTMLInputElement::TabIndexDefault() uint32_t HTMLInputElement::Height() { + if (mType != NS_FORM_INPUT_IMAGE) { + return 0; + } return GetWidthHeightForImage(mCurrentRequest).height; } @@ -1213,6 +1216,9 @@ HTMLInputElement::SetIndeterminate(bool aValue) uint32_t HTMLInputElement::Width() { + if (mType != NS_FORM_INPUT_IMAGE) { + return 0; + } return GetWidthHeightForImage(mCurrentRequest).width; } diff --git a/content/html/content/test/forms/test_input_attributes_reflection.html b/content/html/content/test/forms/test_input_attributes_reflection.html index bda9ff20557..89a0c342b8a 100644 --- a/content/html/content/test/forms/test_input_attributes_reflection.html +++ b/content/html/content/test/forms/test_input_attributes_reflection.html @@ -8,7 +8,7 @@

    -